home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / actors / SMACKv1.0.st < prev    next >
Text File  |  1993-07-24  |  87KB  |  3,131 lines

  1. "    NAME        SMACKv1.0
  2.     AUTHOR        manchester
  3.     FUNCTION    ?
  4.     ST-VERSION    2.2
  5.     PREREQUISITES    
  6.     CONFLICTS
  7.     DISTRIBUTION    world
  8.     VERSION        1
  9.     DATE    16 Aug 1988"
  10. Model subclass: #ActorInterpreter
  11.     instanceVariableNames: 'activeActor activeList running auto stopWhenEmpty processing '
  12.     classVariableNames: ''
  13.     poolDictionaries: ''
  14.     category: 'Actors-Interpreter'!
  15. ActorInterpreter comment:
  16. 'I represent an interpreter for actors.  I maintain a list of active
  17. actors, which I process when sent the `runProcess'' message
  18. (usually from a controller).  My instance variables:
  19.  
  20. activeActor    <Actor> which is currently processing a message, or (nil).
  21.  
  22. activeList    <ActorCollection> of active actors; i.e. actors which
  23.             have one or more Tasks on their mail queues.
  24.  
  25. running        <Boolean> if true, execute the next active actor when send the
  26.             runProcess message.  Otherwise, do nothing.
  27.  
  28. auto        <Boolean> if true, will interpret actors from the activeList even
  29.             when my controller (if any) does not have control.
  30.  
  31. processing    <Boolean> if true, I am currently running in `auto'' mode.  Continue
  32.             to process further actors until the activeList is empty.
  33.  
  34. stopWhenEmpty        <Boolean> if true, reset the running flag when the active
  35.             list becomes empty.
  36.  
  37. The `auto'' and `stopWhenEmpty'' flags are interpreted to give the "mode" of
  38. the instance:
  39.  
  40. auto    stopWhenEmpty        mode
  41. ----------------------------
  42. false        false            normal
  43. false        true            manual
  44. true        false            auto
  45. true        true            *invalid*
  46. '!
  47.  
  48.  
  49. !ActorInterpreter methodsFor: 'initialize-release'!
  50.  
  51. initialize
  52.     "Initialize the instance variables."
  53.  
  54.     activeList _ ActorCollection new.
  55.     running _ true.
  56.     stopWhenEmpty _ false.
  57.     auto _ true.
  58.     processing _ false!
  59.  
  60. release
  61.     "Release any views, or other dependents."
  62.  
  63.     activeActor release.
  64.     activeList release.
  65.     self changed: #release.
  66.     super release! !
  67.  
  68. !ActorInterpreter methodsFor: 'accessing'!
  69.  
  70. activeList
  71.     "Answer with the list of active actors which I am processing."
  72.  
  73.     ^activeList!
  74.  
  75. auto
  76.     "Answer with the state of the auto flag."
  77.  
  78.     ^auto!
  79.  
  80. auto: bool
  81.     "Set the state of the auto flag to bool."
  82.  
  83.     auto _ bool!
  84.  
  85. includes: anActor
  86.     "Answer true if the receiver already refers to anActor, otherwise false."
  87.  
  88.     ^activeList includes: anActor!
  89.  
  90. running
  91.     "Answer whether the receiver is runnable."
  92.  
  93.     ^running!
  94.  
  95. size
  96.     "Answer with the number of active actors on my list."
  97.  
  98.     ^activeList size!
  99.  
  100. stopWhenEmpty
  101.     "Answer with the state of the stopWhenEmpty flag."
  102.  
  103.     ^stopWhenEmpty!
  104.  
  105. stopWhenEmpty: bool
  106.     "Set the state of the stopWhenEmpty flag to bool."
  107.  
  108.     stopWhenEmpty _ bool! !
  109.  
  110. !ActorInterpreter methodsFor: 'adding'!
  111.  
  112. addActor: anActor
  113.     "Add anActor as one to be executed by the receiver."
  114.  
  115.     (anActor == activeActor) ifFalse: [
  116.         activeList addLast: anActor.
  117.         self changed: #activeActors.
  118.         (auto & running & processing not) ifTrue: [
  119.             processing _ true.
  120.             self processAllActors]]! !
  121.  
  122. !ActorInterpreter methodsFor: 'removing'!
  123.  
  124. removeActor: anActor
  125.     "Remove anActor from the list known about by the receiver."
  126.  
  127.     activeList remove: anActor ifAbsent: [^self].
  128.     self changed: #activeActor! !
  129.  
  130. !ActorInterpreter methodsFor: 'processing'!
  131.  
  132. processActor
  133.     "Process a single task from the first actor on the receiver's list.
  134.      Insert the actor at the end of the active list if it has further
  135.      items on its mail queue."
  136.  
  137.     | currentTask |
  138.     activeActor _ activeList removeFirst.
  139.     currentTask _ activeActor getMessage.
  140.     currentTask isNil ifFalse: [
  141.         currentTask target == activeActor mailAddress ifFalse: [
  142.                         self error: 'actor has received task not addressed to it'].
  143.         activeActor behaviour block
  144.             value: activeActor
  145.             value: activeActor aquaintances
  146.             value: currentTask communication.
  147.                 currentTask release].
  148.     activeActor moreMessages
  149.         ifTrue: [activeList addLast: activeActor]
  150.         ifFalse: [self changed: #activeActor].
  151.     activeActor _ nil!
  152.  
  153. processAllActors
  154.     "Process the entire active list."
  155.  
  156.     [processing & running] whileTrue: [self processOneActor]!
  157.  
  158. processOneActor
  159.     "Process the first Task on the mail queue of the first actor in the 
  160.      receiver's active list, if any.  Insert the actor at the end of the 
  161.      active list if it has further items on its mail queue."
  162.  
  163.     activeList isEmpty
  164.         ifTrue: [
  165.             processing _ false.
  166.             stopWhenEmpty ifTrue: [
  167.                 running _ false.
  168.                 self changed: #stopped]]
  169.         ifFalse: [self processActor]!
  170.  
  171. runProcess
  172.     "If the receiver is running, process the next actor from the
  173.      process list."
  174.  
  175.     running ifTrue: [self processOneActor]!
  176.  
  177. startProcessing
  178.     "Start the receiver processing further actors."
  179.  
  180.     running _ true!
  181.  
  182. stopProcessing
  183.     "Stop the receiver from processing further actors."
  184.  
  185.     running _ false! !
  186. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  187.  
  188. ActorInterpreter class
  189.     instanceVariableNames: ''!
  190.  
  191.  
  192. !ActorInterpreter class methodsFor: 'instance creation'!
  193.  
  194. new
  195.     "Answer with a new initialized instance of the receiver."
  196.  
  197.     ^super new initialize! !
  198.  
  199. Dictionary variableSubclass: #ActorDictionary
  200.     instanceVariableNames: ''
  201.     classVariableNames: ''
  202.     poolDictionaries: ''
  203.     category: 'Actors-Simulation'!
  204. ActorDictionary comment:
  205. 'I am a subclass of Dictionary which knows about active inspectors.'!
  206.  
  207.  
  208. !ActorDictionary methodsFor: 'initialize-release'!
  209.  
  210. release
  211.     "Release any views on me."
  212.  
  213.     self associationsDo: [:eachAssociation |
  214.         eachAssociation key release.
  215.         eachAssociation value release].
  216.     self changed: #release.
  217.     super release! !
  218.  
  219. !ActorDictionary methodsFor: 'accessing'!
  220.  
  221. at: key put: value
  222.     "Override the method in the superclass in order to signal changes."
  223.  
  224.     | temp |
  225.     temp _ super at: key put: value.
  226.     self changed: #all.
  227.     ^temp! !
  228.  
  229. !ActorDictionary methodsFor: 'dictionary removing'!
  230.  
  231. removeKey: key ifAbsent: aBlock
  232.     "Override the method in the superclass in order to signal changes."
  233.  
  234.     | temp |
  235.     temp _ super removeKey: key ifAbsent: aBlock.
  236.     self changed: #all.
  237.     ^temp! !
  238.  
  239. !ActorDictionary methodsFor: 'inspecting'!
  240.  
  241. inspect
  242.     "Use special dictionary inspector for actor simulations."
  243.  
  244.     SMACKInspectorView open: (ActorDictionaryInspector inspect: self)!
  245.  
  246. labelString
  247.     "Answer with a string suitable for use as a view's label."
  248.  
  249.     ^self class name! !
  250.  
  251. OrderedCollection variableSubclass: #ActorCollection
  252.     instanceVariableNames: ''
  253.     classVariableNames: ''
  254.     poolDictionaries: ''
  255.     category: 'Actors-Simulation'!
  256. ActorCollection comment:
  257. 'I am a subclass of OrderedCollection which knows about
  258. interactive inspectors.'!
  259.  
  260.  
  261. !ActorCollection methodsFor: 'initialize-release'!
  262.  
  263. release
  264.     "Release any views on me."
  265.  
  266.     self do: [:each | each release].
  267.     self changed: #release.
  268.     super release! !
  269.  
  270. !ActorCollection methodsFor: 'accessing'!
  271.  
  272. at: anInteger put: anObject
  273.     "Override the method in the superclass in order to indicate changes."
  274.  
  275.     | temp |
  276.     temp _ super at: anInteger put: anObject.
  277.     self changed: #all.
  278.     ^temp! !
  279.  
  280. !ActorCollection methodsFor: 'adding'!
  281.  
  282. addLast: newObject
  283.     "Override the method in the sueprclass in order to signal changes."
  284.  
  285.     | temp |
  286.     temp _ super addLast: newObject.
  287.     self changed: #all.
  288.     ^temp! !
  289.  
  290. !ActorCollection methodsFor: 'removing'!
  291.  
  292. remove: oldObject ifAbsent: aBlock
  293.     "Override the method in the superclass in order to signal changes."
  294.  
  295.     | temp |
  296.     temp _ super remove: oldObject ifAbsent: aBlock.
  297.     self changed: #all.
  298.     ^temp!
  299.  
  300. removeFirst
  301.     "Override the method in the superclass in order to signal changes."
  302.  
  303.     | temp |
  304.     temp _ super removeFirst.
  305.     self changed: #all.
  306.     ^temp!
  307.  
  308. removeLast
  309.     "Override the method in the superclass in order to signal changes."
  310.  
  311.     | temp |
  312.     temp _ super removeLast.
  313.     self changed: #all.
  314.     ^temp! !
  315.  
  316. !ActorCollection methodsFor: 'inspecting'!
  317.  
  318. inspect
  319.     "Use special inspector for actor simulations."
  320.  
  321.     SMACKInspectorView open: (ActorCollectionInspector inspect: self)!
  322.  
  323. labelString
  324.     "Answer with a string suitable for use as a view's label."
  325.  
  326.     ^self class name! !
  327.  
  328. !ActorCollection methodsFor: 'private'!
  329.  
  330. insert: anObject before: spot
  331.     "Override the method in the superclass in order to signal changes."
  332.  
  333.     | temp |
  334.     temp _ super insert: anObject before: spot.
  335.     self changed: #all.
  336.     ^temp! !
  337.  
  338. Model subclass: #ActorModel
  339.     instanceVariableNames: ''
  340.     classVariableNames: ''
  341.     poolDictionaries: ''
  342.     category: 'Actors-Simulation'!
  343. ActorModel comment:
  344. 'I represent the abstract superclass of `dynamic'' actor entities; i.e. those
  345. which are created and destroyed as the system runs.'!
  346.  
  347.  
  348. !ActorModel methodsFor: 'initialize-release'!
  349.  
  350. release
  351.     "Remove any views on me.  Subclasses should include 'super release'
  352.      in any re-implementations."
  353.  
  354.     self changed: #release.
  355.     super release! !
  356.  
  357. !ActorModel methodsFor: 'inspecting'!
  358.  
  359. inspect
  360.     "Use special inspector for actor simulations."
  361.  
  362.     SMACKInspectorView open: (SMACKInspector inspect: self)!
  363.  
  364. labelString
  365.     "Answer with a string suitable for use as a view's label."
  366.  
  367.     ^self printString! !
  368.  
  369. ActorModel subclass: #MailSystem
  370.     instanceVariableNames: 'table '
  371.     classVariableNames: ''
  372.     poolDictionaries: ''
  373.     category: 'Actors-Simulation'!
  374. MailSystem comment:
  375. 'I represent a mail system capable of routing messages (Tasks) from one
  376. actor to another.
  377.  
  378. My instance variables are:
  379.  
  380. table        <ActorDictionary> with <key> being a <MailAddress>, and <value>
  381.             being a <Actor>.'!
  382.  
  383.  
  384. !MailSystem methodsFor: 'initialize-release'!
  385.  
  386. initialize
  387.     "Initialize the address table."
  388.  
  389.     table _ ActorDictionary new!
  390.  
  391. release
  392.     "Release my instance variables."
  393.  
  394.     table release.
  395.     super release! !
  396.  
  397. !MailSystem methodsFor: 'accessing'!
  398.  
  399. table
  400.     "Answer with the table of addresses.  Only used by the inspector."
  401.  
  402.     ^table! !
  403.  
  404. !MailSystem methodsFor: 'adding'!
  405.  
  406. addAddress: mailAddress to: actor
  407.     "Insert the mail address mailAddress to the Actor actor in the
  408.     routing table.  Answer with the actor inserted."
  409.  
  410.     table at: mailAddress put: actor.
  411.     self changed: #all.
  412.     ^actor! !
  413.  
  414. !MailSystem methodsFor: 'removing'!
  415.  
  416. removeAddress: mailAddr
  417.     "Remove knowledge of the mail address mailAddr, and the associated
  418.      actor, from the routing table. Answer with the actor associated with
  419.      mailAddr.  Create a error message if the mailAddr is unknown."
  420.  
  421.     | temp |
  422.     temp _ table
  423.         removeKey: mailAddr
  424.         ifAbsent: ["self error:
  425.             'Trying to remove a non-existent mail address'." ^nil].
  426.     self changed: #all.
  427.     ^temp value! !
  428.  
  429. !MailSystem methodsFor: 'sending'!
  430.  
  431. send: aTask to: aMailAddress
  432.     "Send aTask to the actor with address
  433.      aMailAddress."
  434.  
  435.     (table at: aMailAddress
  436.         ifAbsent: [^self error: 'Trying to send to non-existent mail address'])
  437.             addMessage: aTask! !
  438.  
  439. !MailSystem methodsFor: 'printing'!
  440.  
  441. printOn: aStream
  442.     "Put a printable representation of the receiver on aStream."
  443.  
  444.     aStream nextPutAll: self class name.
  445.     aStream nextPutAll: ' ('.
  446.     table size printOn: aStream.
  447.     aStream nextPut: $)! !
  448.  
  449. !MailSystem methodsFor: 'garbage collection'!
  450.  
  451. garbageCollect
  452.     "Remove unwanted actors from the mail system."
  453.     "MailAddress mailer garbageCollect."
  454.  
  455.     | g1 g2 actor size |
  456.     g1 _ Smalltalk select: [:g | g class == MailAddress].
  457.     g2 _ ActorDictionary new.
  458.     g1 associationsDo: [:eachAssociation |
  459.         g2
  460.             at: (Smalltalk at: eachAssociation key)
  461.             put: (self removeAddress: eachAssociation value)].
  462.     size _ table size.
  463.     table release.
  464.  
  465.     self initialize.
  466.     Smalltalk garbageCollect.
  467.     Transcript show: 'Collected ', size printString, ' actors'; cr.
  468.     g2 associationsDo: [:e | self addAddress: e key to: e value]! !
  469. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  470.  
  471. MailSystem class
  472.     instanceVariableNames: ''!
  473.  
  474.  
  475. !MailSystem class methodsFor: 'instance creation'!
  476.  
  477. new
  478.     "Create a new initialized instance of the receiver."
  479.  
  480.     ^super new initialize! !
  481.  
  482. ActorModel subclass: #MailAddress
  483.     instanceVariableNames: ''
  484.     classVariableNames: 'Mailer '
  485.     poolDictionaries: ''
  486.     category: 'Actors-Simulation'!
  487. MailAddress comment:
  488. 'I represent a unique mail address to which messages may be
  489. sent.  Messages are routed by an instance of <MailSystem>,
  490. referred to by my class variable `Mailer''.  Mail addresses do not
  491. change.'!
  492.  
  493.  
  494. !MailAddress methodsFor: 'initialize-release'!
  495.  
  496. release
  497.     "Remove my actor from the mail system."
  498.  
  499.     self removeAddress.
  500.     super release! !
  501.  
  502. !MailAddress methodsFor: 'adding'!
  503.  
  504. addAddressTo: actor
  505.     "Add the receiver as a mail address to the Actor actor, in the mail system."
  506.  
  507.     Mailer addAddress: self to: actor! !
  508.  
  509. !MailAddress methodsFor: 'removing'!
  510.  
  511. removeAddress
  512.     "Remove the receiver as a mail address known about by the
  513.      mail system."
  514.  
  515.     Mailer removeAddress: self! !
  516.  
  517. !MailAddress methodsFor: 'sending'!
  518.  
  519. send: aTask
  520.     "Send aTask to the actor with mail address represented by
  521.      the receiver."
  522.  
  523.     Mailer send: aTask to: self!
  524.  
  525. sendCommunication: aCommunication
  526.     "Create a task with aCommunication, and send it to the actor
  527.      represented by the receiver."
  528.  
  529.     (Task communication: aCommunication target: self) send!
  530.  
  531. sendMessage: aSymbol
  532.     "Create a task with a communication with name aSymbol and no
  533.      arguments, and send it to the actor represented by the receiver."
  534.  
  535.     self sendCommunication: (Communication name: aSymbol)!
  536.  
  537. sendMessage: aSymbol with: firstArgument
  538.     "Create a task with a communication with name aSymbol and one
  539.      argument, and send it to the actor represented by the receiver."
  540.  
  541.     self sendCommunication: (Communication name: aSymbol with: firstArgument)!
  542.  
  543. sendMessage: aSymbol with: firstArgument with: secondArgument
  544.     "Create a task with a communication with name aSymbol and two
  545.      arguments, and send it to the actor represented by the receiver."
  546.  
  547.     self sendCommunication: (
  548.         Communication
  549.             name: aSymbol
  550.             with: firstArgument
  551.             with: secondArgument)!
  552.  
  553. sendMessage: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  554.     "Create a task with a communication with name aSymbol and three
  555.      arguments, and send it to the actor represented by the receiver."
  556.  
  557.     self sendCommunication: (
  558.         Communication
  559.             name: aSymbol
  560.             with: firstArgument
  561.             with: secondArgument
  562.             with: thirdArgument)!
  563.  
  564. sendMessage: aSymbol withArguments: anArray
  565.     "Create a task with a communication with name aSymbol and
  566.      arguments from anArray, and send it to the actor represented
  567.      by the receiver."
  568.  
  569.     self sendCommunication: (Communication name: aSymbol withArguments: anArray)! !
  570.  
  571. !MailAddress methodsFor: 'printing'!
  572.  
  573. labelString
  574.     "Answer with a string suitable for use as a label."
  575.  
  576.     ^self class name, ' (', self printString, ')'!
  577.  
  578. printOn: aStream
  579.     "Put a printable representation of the receiver on aStream."
  580.  
  581.     aStream nextPutAll: self asOop printString! !
  582.  
  583. !MailAddress methodsFor: 'inspecting'!
  584.  
  585. inspect
  586.     "Use special inspector for mail addresses."
  587.  
  588.     SMACKInspectorView open: (MailAddressInspector inspect: self)! !
  589. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  590.  
  591. MailAddress class
  592.     instanceVariableNames: ''!
  593.  
  594.  
  595. !MailAddress class methodsFor: 'class initialization'!
  596.  
  597. initialize
  598.     "Initialize my class variable, which represents a mail system
  599.      capable of routing messages between actors."
  600.     "MailAddress initialize."
  601.  
  602.     Mailer notNil ifTrue: [Mailer release].
  603.     Mailer _ MailSystem new! !
  604.  
  605. !MailAddress class methodsFor: 'class access'!
  606.  
  607. mailer
  608.     "Answer with the current instance of MailSystem being used by
  609.      the receiver."
  610.  
  611.     ^Mailer! !
  612.  
  613. MailAddress initialize!
  614.  
  615.  
  616. ActorModel subclass: #Aquaintances
  617.     instanceVariableNames: 'contents '
  618.     classVariableNames: ''
  619.     poolDictionaries: ''
  620.     category: 'Actors-Simulation'!
  621. Aquaintances comment:
  622. 'I represent a list of aquaintances.  My instance variable is:
  623.  
  624. contents    <Dictionary> with <key> being a <Symbol> (my name for
  625.             the aquaintance), and <value> being a <MailAddress> for
  626.             the aquaintance.
  627. '!
  628.  
  629.  
  630. !Aquaintances methodsFor: 'initialize-release'!
  631.  
  632. initialize
  633.     "Initialize the instance variable."
  634.  
  635.     contents _ ActorDictionary new.!
  636.  
  637. release
  638.     "Release all my instance variables."
  639.  
  640.     contents release.
  641.     super release! !
  642.  
  643. !Aquaintances methodsFor: 'accessing'!
  644.  
  645. contents
  646.     "Answer with the entire aquaintance dictionary."
  647.  
  648.     ^contents!
  649.  
  650. name: aSymbol
  651.     "Answer with the mail address of an actor known by the receiver
  652.      as aSymbol.  Create an error message if aSymbol is not found."
  653.  
  654.     ^contents
  655.         at: aSymbol
  656.         ifAbsent: [self error: 'Attempted to access an aquaintance which is unknown']!
  657.  
  658. name: aSymbol mailAddress: aMailAddress
  659.     "Insert the aquaintance known as aSymbol with address aMailAddress."
  660.  
  661.     contents at: aSymbol put: aMailAddress.
  662.     self changed: #all! !
  663.  
  664. !Aquaintances methodsFor: 'sending'!
  665.  
  666. name: aName sendCommunication: aCommunication
  667.     "Send a Task containing aCommunication to the mailAddress
  668.      accessed by aName."
  669.  
  670.     (self name: aName) sendCommunication: aCommunication!
  671.  
  672. name: aName sendMessage: aSymbol
  673.     "Send a message called aSymbol to the mailAddress
  674.      accessed by aName."
  675.  
  676.     (self name: aName) sendMessage: aSymbol!
  677.  
  678. name: aName sendMessage: aSymbol with: firstArgument
  679.     "Send a message called aSymbol with one argument to the mailAddress
  680.      accessed by aName."
  681.  
  682.     (self name: aName) sendMessage: aSymbol with: firstArgument!
  683.  
  684. name: aName sendMessage: aSymbol with: firstArgument with: secondArgument
  685.     "Send a message called aSymbol with two arguments to the mailAddress
  686.      accessed by aName."
  687.  
  688.     (self name: aName)
  689.         sendMessage: aSymbol
  690.         with: firstArgument
  691.         with: secondArgument!
  692.  
  693. name: aName sendMessage: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  694.     "Send a message called aSymbol with three arguments to the mailAddress
  695.      accessed by aName."
  696.  
  697.     (self name: aName)
  698.         sendMessage: aSymbol
  699.         with: firstArgument
  700.         with: secondArgument
  701.         with: thirdArgument!
  702.  
  703. name: aName sendMessage: aSymbol withArguments: anArray
  704.     "Send a message called aSymbol with arguments from anArray
  705.      to the mailAddress accessed by aName."
  706.  
  707.     (self name: aName) sendMessage: aSymbol withArguments: anArray! !
  708.  
  709. !Aquaintances methodsFor: 'printing'!
  710.  
  711. printOn: aStream
  712.     "Put a printable representation of the receiver on aStream."
  713.  
  714.     self class name printOn: aStream.
  715.     aStream nextPutAll: ' (', contents size printString, ')'! !
  716. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  717.  
  718. Aquaintances class
  719.     instanceVariableNames: ''!
  720.  
  721.  
  722. !Aquaintances class methodsFor: 'instance creation'!
  723.  
  724. name: aSymbol mailAddress: aMailAddress
  725.     "Answer with an instance of the receiver which knows about
  726.      aSymbol referring to aMailAddress."
  727.  
  728.     ^self new name: aSymbol mailAddress: aMailAddress!
  729.  
  730. name: s1 mailAddress: m1 name: s2 mailAddress: m2
  731.     "Answer with an instance of the receiver which knows about
  732.      s1 referring to m1, and s2 referring to m3."
  733.  
  734.     ^(self new name: s1 mailAddress: m1) name: s2 mailAddress: m2!
  735.  
  736. new
  737.     "Answer with a new initialized instance of the receiver."
  738.  
  739.     ^super new initialize! !
  740.  
  741. ActorModel subclass: #Actor
  742.     instanceVariableNames: 'mailAddress behaviour mailQueue aquaintances '
  743.     classVariableNames: 'Interpreter '
  744.     poolDictionaries: ''
  745.     category: 'Actors-Simulation'!
  746. Actor comment:
  747. 'I represent a potentially concurrent object.
  748.  
  749. My instance variables are:
  750.  
  751. behaviour        <Behaviour> describing my actions when a message is
  752.                 received.
  753.  
  754. mailAddress        <MailAddress> representing the unique identity of an
  755.                 instance of me.
  756.  
  757. mailQueue        <MailQueue> representing messages to be processed.
  758.  
  759. aquaintances    <Aquaintances> representing my names for other actors
  760.                 instances of me know about.
  761.  
  762.  
  763. My class variable "Interpreter" is an instance of <ActorInterpreter> which
  764. represents the execution engine for instances of this class.'!
  765.  
  766.  
  767. !Actor methodsFor: 'initialize-release'!
  768.  
  769. initialize
  770.     "Initialize the mail address, mail queue and aquaintances instance
  771.      variables."
  772.  
  773.     mailAddress _ MailAddress new.
  774.     mailAddress addAddressTo: self.
  775.     mailQueue _ MailQueue new.
  776.     aquaintances _ Aquaintances new.!
  777.  
  778. release
  779.     "Nil out the receiver's mail address, to break up possible cycles.
  780.      Remove the receiver from the list maintained by the interpreter.
  781.      Release all the receiver's instance variables."
  782.  
  783.     mailAddress _ nil.
  784.     mailQueue release.
  785.     behaviour release.
  786.     aquaintances release.
  787.     Interpreter removeActor: self.
  788.     super release! !
  789.  
  790. !Actor methodsFor: 'accessing'!
  791.  
  792. aquaintances
  793.     "Answer with the aquaintances of the receiver.  Only used by the interpreter."
  794.  
  795.     ^aquaintances!
  796.  
  797. behaviour
  798.     "Answer with the behaviour of the receiver.  Only used by the interpreter."
  799.  
  800.     ^behaviour!
  801.  
  802. mailAddress
  803.     "Answer with the mail address of the receiver."
  804.  
  805.     ^mailAddress! !
  806.  
  807. !Actor methodsFor: 'messages'!
  808.  
  809. addMessage: aMessage
  810.     "Add aMessage to the receiver's queue of messages."
  811.  
  812.     | test |
  813.     test _ mailQueue isEmpty.
  814.     mailQueue addMessage: aMessage.
  815.     test ifTrue: [Interpreter addActor: self].
  816.     self changed: #all!
  817.  
  818. getMessage
  819.     "Answer with the first message from the mail queue.  Only used by
  820.      the interpreter."
  821.  
  822.     | task |
  823.     task _ mailQueue getMessage.
  824.     self changed: #all.
  825.     ^task!
  826.  
  827. moreMessages
  828.     "Answer true if there are further messages to process, otherwise
  829.      false."
  830.  
  831.     ^mailQueue isEmpty not! !
  832.  
  833. !Actor methodsFor: 'behaviour'!
  834.  
  835. becomes: aBehaviour
  836.     "The behaviour of the receiver becomes aBehaviour.  The
  837.      aquaintances are unchanged."
  838.  
  839.     behaviour _ aBehaviour.
  840.     self changed: #all!
  841.  
  842. becomes: aBehaviour withAquaintances: anAquaintances
  843.     "The behaviour of the receiver becomes aBehaviour, with
  844.      aquaintances anAquaintances."
  845.  
  846.     behaviour _ aBehaviour.
  847.     aquaintances _ anAquaintances.
  848.     self changed: #all! !
  849.  
  850. !Actor methodsFor: 'printing'!
  851.  
  852. printOn: aStream
  853.     "Put a printable representation of the receiver on aStream."
  854.  
  855.     aStream nextPutAll: self class name.
  856.     aStream nextPutAll: ' ('.
  857.     mailAddress printOn: aStream.
  858.     aStream nextPut: $)! !
  859.  
  860. !Actor methodsFor: 'private'!
  861.  
  862. setAquaintances: anAquaintances
  863.     "Set the aquaintances of the receiver to anAquaintances."
  864.  
  865.     aquaintances _ anAquaintances! !
  866. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  867.  
  868. Actor class
  869.     instanceVariableNames: ''!
  870.  
  871.  
  872. !Actor class methodsFor: 'instance creation'!
  873.  
  874. new
  875.     "Answer with a new initialized instance of the receiver."
  876.  
  877.     ^super new initialize!
  878.  
  879. withAquaintances: anAquaintances
  880.     "Create a new instance of the receiver, with aquaintances
  881.      defined by anAquaintances.  Answer with the mail address of
  882.      the new instance."
  883.  
  884.     ^(self new setAquaintances: anAquaintances) mailAddress!
  885.  
  886. withAquaintances: anAquaintances withBehaviour: aBehaviour
  887.     "Create a new instance of the receiver, with aquaintances
  888.      defined by anAquaintances, and behaviour defined by aBehaviour.
  889.      Answer with the mail address of the new instance."
  890.  
  891.     | temp |
  892.     temp _ self new setAquaintances: anAquaintances.
  893.     temp becomes: aBehaviour.
  894.     ^temp mailAddress!
  895.  
  896. withBehaviour: aBehaviour
  897.     "Create a new instance of the receiver, with behaviour
  898.      defined by aBehaviour.  Answer with the mail address of the new
  899.      instance."
  900.  
  901.     ^(self new becomes: aBehaviour) mailAddress!
  902.  
  903. withBehaviour: aBehaviour withAquaintances: anAquaintances
  904.     "Create a new instance of the receiver, with aquaintances
  905.      defined by anAquaintances, and behaviour defined by aBehaviour.
  906.      Answer with the mail address of the new instance."
  907.  
  908.     | temp |
  909.     temp _ self new setAquaintances: anAquaintances.
  910.     temp becomes: aBehaviour.
  911.     ^temp mailAddress! !
  912.  
  913. !Actor class methodsFor: 'class initialization'!
  914.  
  915. initialize
  916.     "Initialize the class variable Interpreter, which represents the
  917.      execution enginer for instances of the receiver."
  918.     "Actor initialize."
  919.  
  920.     Interpreter notNil ifTrue: [Interpreter release].
  921.     Interpreter _ ActorInterpreter new.! !
  922.  
  923. !Actor class methodsFor: 'class access'!
  924.  
  925. interpreter
  926.     "Answer with the current instance of ActorInterpreter in use by
  927.      the receiver."
  928.      "Actor interpreter."
  929.  
  930.     ^Interpreter! !
  931.  
  932. !Actor class methodsFor: 'examples'!
  933.  
  934. exampleWorkspace1
  935.     "Select and execute the expressions here to play with actors."
  936.  
  937.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  938.     ActorTextCollector open.        "Open a view on the actor transcript."
  939.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  940.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  941.  
  942.     ActorTranscript sendMessage: #clear.
  943.     ActorTranscript sendMessage: #show with: 'Hello, world!!'.!
  944.  
  945. exampleWorkspace10
  946.     "Select and execute the expressions here to run a timed fibonacci example."
  947.  
  948.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  949.     ActorTextCollector open.        "Open a view on the actor transcript."
  950.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  951.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  952.  
  953.     "This bit creates a global actor capable of timing."
  954.     "
  955.     Smalltalk at: #ActorTimer put:
  956.         (Actor withBehaviour:
  957.             (Behaviour block: [:slf :acq :com |
  958.                 (com name == #now) ifTrue: [
  959.                     (com at: 1)
  960.                         sendMessage: #reply
  961.                         withArguments: (Time dateAndTimeNow)].
  962.                 (com name == #milliseconds) ifTrue: [
  963.                     (com at: 1)
  964.                         sendMessage: #reply
  965.                         with: (Time millisecondClockValue)]])).
  966.     "
  967.     "This bit finds the time taken for 'null' activity."
  968.     "
  969.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  970.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  971.         (com name == #start) ifTrue: [
  972.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  973.             slf becomes: secondBehaviour]].
  974.  
  975.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  976.         (com name == #reply) ifTrue: [
  977.  
  978.             slf mailAddress sendMessage: #reply with: 1.
  979.  
  980.             slf
  981.                 becomes: thirdBehaviour
  982.                 withAquaintances: (Aquaintances
  983.                     name: #startTime mailAddress: (com at: 1))]].
  984.  
  985.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  986.         (com name == #reply) ifTrue: [
  987.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  988.             slf becomes: fourthBehaviour]].
  989.  
  990.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  991.         (com name == #reply) ifTrue: [
  992.             ActorTranscript sendMessage: #cr.
  993.             ActorTranscript
  994.                 sendMessage: #show
  995.                 with: 'Time taken for no activity was: '.
  996.             ActorTranscript sendMessage: #show with:
  997.                 ((com at: 1) - (acq name: #startTime)) printString.
  998.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  999.  
  1000.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1001.     "
  1002.     "This bit actually runs the fibonacci example."
  1003.     "
  1004.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  1005.       fibonacciBehaviour waitBothBehaviour waitOneBehaviour |
  1006.  
  1007.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1008.         (com name == #start) ifTrue: [
  1009.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1010.             slf becomes: secondBehaviour]].
  1011.  
  1012.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1013.         (com name == #reply) ifTrue: [
  1014.             (Actor
  1015.                 withBehaviour: fibonacciBehaviour
  1016.                 withAquaintances: (Aquaintances
  1017.                     name: #replyTo
  1018.                     mailAddress: slf mailAddress))
  1019.                 sendMessage: #fibonacci with: 13.
  1020.             slf
  1021.                 becomes: thirdBehaviour
  1022.                 withAquaintances: (Aquaintances
  1023.                     name: #startTime mailAddress: (com at: 1))]].
  1024.  
  1025.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1026.         (com name == #reply) ifTrue: [
  1027.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1028.             slf becomes: fourthBehaviour]].
  1029.  
  1030.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1031.         (com name == #reply) ifTrue: [
  1032.             ActorTranscript sendMessage: #cr.
  1033.             ActorTranscript
  1034.                 sendMessage: #show
  1035.                 with: 'Time taken for fibonacci (13) was: '.
  1036.             ActorTranscript sendMessage: #show with:
  1037.                 ((com at: 1) - (acq name: #startTime)) printString.
  1038.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1039.  
  1040.     fibonacciBehaviour _ Behaviour block: [:slf :acq :com |
  1041.         (com name == #fibonacci) ifTrue: [
  1042.             ((com at: 1) <= 1)
  1043.                 ifTrue: [
  1044.                     (acq name: #replyTo) sendMessage: #reply with: (com at: 1)]
  1045.                 ifFalse: [
  1046.                     slf becomes: waitBothBehaviour.
  1047.                     (Actor
  1048.                         withBehaviour: fibonacciBehaviour
  1049.                         withAquaintances: (Aquaintances
  1050.                             name: #replyTo
  1051.                             mailAddress: slf mailAddress))
  1052.                                 sendMessage: #fibonacci
  1053.                                 with: ((com at: 1) - 1).
  1054.                     (Actor
  1055.                         withBehaviour: fibonacciBehaviour
  1056.                         withAquaintances: (Aquaintances
  1057.                             name: #replyTo
  1058.                             mailAddress: slf mailAddress))
  1059.                                 sendMessage: #fibonacci
  1060.                                 with: ((com at: 1) - 2)]]].
  1061.  
  1062.     waitBothBehaviour _ Behaviour block: [:slf :acq :com |
  1063.         (com name == #reply) ifTrue: [
  1064.             slf
  1065.                 becomes: waitOneBehaviour
  1066.                 withAquaintances: (Aquaintances
  1067.                     name: #replyTo mailAddress: (acq name: #replyTo)
  1068.                     name: #first mailAddress: (com at: 1))]].
  1069.  
  1070.     waitOneBehaviour _ Behaviour block: [:slf :acq :com |
  1071.         (com name == #reply) ifTrue: [
  1072.             (acq name: #replyTo)
  1073.                 sendMessage: #reply
  1074.                 with: ((acq name: #first) + (com at: 1))]].
  1075.  
  1076.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1077.     "!
  1078.  
  1079. exampleWorkspace11
  1080.     "Select and execute the expressions here to run an iterative factorial example."
  1081.  
  1082.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1083.     ActorTextCollector open.        "Open a view on the actor transcript."
  1084.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1085.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1086.  
  1087.     "
  1088.     | startBehaviour iterateBehaviour |
  1089.  
  1090.     startBehaviour _ Behaviour block: [:slf :acq :com |
  1091.         (com name == #factorial) ifTrue: [
  1092.             slf
  1093.                 becomes: iterateBehaviour
  1094.                 withAquaintances: (Aquaintances
  1095.                     name: #current mailAddress: 1
  1096.                     name: #replyTo mailAddress: (acq name: #replyTo)).
  1097.             slf mailAddress sendMessage: #iterate with: (com at: 1)]].
  1098.  
  1099.     iterateBehaviour _ Behaviour block: [:slf :acq :com |
  1100.         (com name == #iterate)
  1101.             ifTrue: [
  1102.                 ((com at: 1) <= 1)
  1103.                     ifTrue: [
  1104.                         slf becomes: startBehaviour    .
  1105.                         (acq name: #replyTo)
  1106.                             sendMessage: #reply with: (acq name: #current)]
  1107.                     ifFalse: [
  1108.                         acq name: #current mailAddress: (acq name: #current) * (com at: 1).
  1109.                         slf mailAddress sendMessage: #iterate with: ((com at: 1) - 1)]]].
  1110.  
  1111.     (Actor
  1112.         withBehaviour: startBehaviour
  1113.         withAquaintances: (Aquaintances
  1114.             name: #replyTo mailAddress: (Actor
  1115.                 withBehaviour: (Behaviour block: [:slf :acq :com |
  1116.                     (com name == #reply) ifTrue: [
  1117.                         ActorTranscript sendMessage: #clear.
  1118.                         ActorTranscript
  1119.                             sendMessage: #show
  1120.                             with: (com at: 1) printString]])))) sendMessage: #factorial with: 20.
  1121.  
  1122.     "!
  1123.  
  1124. exampleWorkspace12
  1125.     "Select and execute the expressions here to run a timed iterative
  1126.      factorial example."
  1127.  
  1128.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1129.     ActorTextCollector open.        "Open a view on the actor transcript."
  1130.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1131.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1132.  
  1133.     "This bit creates a global actor capable of timing."
  1134.     "
  1135.     Smalltalk at: #ActorTimer put:
  1136.         (Actor withBehaviour:
  1137.             (Behaviour block: [:slf :acq :com |
  1138.                 (com name == #now) ifTrue: [
  1139.                     (com at: 1)
  1140.                         sendMessage: #reply
  1141.                         withArguments: (Time dateAndTimeNow)].
  1142.                 (com name == #milliseconds) ifTrue: [
  1143.                     (com at: 1)
  1144.                         sendMessage: #reply
  1145.                         with: (Time millisecondClockValue)]])).
  1146.     "
  1147.     "This bit finds the time taken for 'null' activity."
  1148.     "
  1149.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  1150.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1151.         (com name == #start) ifTrue: [
  1152.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1153.             slf becomes: secondBehaviour]].
  1154.  
  1155.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1156.         (com name == #reply) ifTrue: [
  1157.  
  1158.             slf mailAddress sendMessage: #reply with: 1.
  1159.  
  1160.             slf
  1161.                 becomes: thirdBehaviour
  1162.                 withAquaintances: (Aquaintances
  1163.                     name: #startTime mailAddress: (com at: 1))]].
  1164.  
  1165.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1166.         (com name == #reply) ifTrue: [
  1167.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1168.             slf becomes: fourthBehaviour]].
  1169.  
  1170.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1171.         (com name == #reply) ifTrue: [
  1172.             ActorTranscript sendMessage: #cr.
  1173.             ActorTranscript
  1174.                 sendMessage: #show
  1175.                 with: 'Time taken for no activity was: '.
  1176.             ActorTranscript sendMessage: #show with:
  1177.                 ((com at: 1) - (acq name: #startTime)) printString.
  1178.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1179.  
  1180.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1181.     "
  1182.     "This bit actually runs the iterative factorial example."
  1183.     "
  1184.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  1185.       startBehaviour iterateBehaviour |
  1186.  
  1187.     startBehaviour _ Behaviour block: [:slf :acq :com |
  1188.         (com name == #factorial) ifTrue: [
  1189.             slf
  1190.                 becomes: iterateBehaviour
  1191.                 withAquaintances: (Aquaintances
  1192.                     name: #current mailAddress: 1
  1193.                     name: #replyTo mailAddress: (acq name: #replyTo)).
  1194.             slf mailAddress sendMessage: #iterate with: (com at: 1)]].
  1195.  
  1196.  
  1197.     iterateBehaviour _ Behaviour block: [:slf :acq :com |
  1198.         (com name == #iterate)
  1199.             ifTrue: [
  1200.                 ((com at: 1) <= 1)
  1201.                     ifTrue: [
  1202.                         slf becomes: startBehaviour    .
  1203.                         (acq name: #replyTo)
  1204.                             sendMessage: #reply with: (acq name: #current)]
  1205.                     ifFalse: [
  1206.                         slf
  1207.                             becomes: iterateBehaviour
  1208.                             withAquaintances: (Aquaintances
  1209.                                 name: #current
  1210.                                 mailAddress: ((acq name: #current) * (com at: 1))
  1211.                                 name: #replyTo
  1212.                                 mailAddress: (acq name: #replyTo)).
  1213.                         slf mailAddress sendMessage: #iterate with: ((com at: 1) - 1)]]].
  1214.  
  1215.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1216.         (com name == #start) ifTrue: [
  1217.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1218.             slf becomes: secondBehaviour]].
  1219.  
  1220.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1221.         (com name == #reply) ifTrue: [
  1222.             (Actor
  1223.                 withBehaviour: startBehaviour
  1224.                 withAquaintances: (Aquaintances
  1225.                     name: #replyTo
  1226.                     mailAddress: slf mailAddress))
  1227.                 sendMessage: #factorial with: 20.
  1228.             slf
  1229.                 becomes: thirdBehaviour
  1230.                 withAquaintances: (Aquaintances
  1231.                     name: #startTime mailAddress: (com at: 1))]].
  1232.  
  1233.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1234.         (com name == #reply) ifTrue: [
  1235.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1236.             slf becomes: fourthBehaviour]].
  1237.  
  1238.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1239.         (com name == #reply) ifTrue: [
  1240.             ActorTranscript sendMessage: #cr.
  1241.             ActorTranscript
  1242.                 sendMessage: #show
  1243.                 with: 'Time taken for factorial (20) was: '.
  1244.             ActorTranscript sendMessage: #show with:
  1245.                 ((com at: 1) - (acq name: #startTime)) printString.
  1246.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1247.  
  1248.  
  1249.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1250.  
  1251.     "!
  1252.  
  1253. exampleWorkspace13
  1254.     "Select and execute the expressions here to run a divide-and-conquor
  1255.      factorial example."
  1256.  
  1257.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1258.     ActorTextCollector open.        "Open a view on the actor transcript."
  1259.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1260.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1261.  
  1262.     "
  1263.     | rangeBehaviour mid waitBothBehaviour waitOneBehaviour sink |
  1264.  
  1265.     rangeBehaviour _ Behaviour block: [:slf :acq :com |
  1266.         (com name == #factorial) ifTrue: [
  1267.             ((com at: 1) = (com at: 2)) ifTrue: [
  1268.                 (acq name: #replyTo) sendMessage: #reply with: (com at: 1)].
  1269.             ((com at: 1) > (com at: 2)) ifTrue: [
  1270.                 (acq name: #replyTo) sendMessage: #reply with: 1].
  1271.             ((com at: 1) < (com at: 2)) ifTrue: [
  1272.                 slf becomes: waitBothBehaviour.
  1273.                 mid _ ((com at: 1) + (com at: 2)) // 2.
  1274.                 (Actor
  1275.                     withBehaviour: rangeBehaviour
  1276.                     withAquaintances: (Aquaintances
  1277.                         name: #replyTo mailAddress: slf mailAddress))
  1278.                             sendMessage: #factorial with: (com at: 1) with: mid.
  1279.                 (Actor
  1280.                     withBehaviour: rangeBehaviour
  1281.                     withAquaintances: (Aquaintances
  1282.                         name: #replyTo mailAddress: slf mailAddress))
  1283.                             sendMessage: #factorial with: (mid + 1) with: (com at: 2)]]].
  1284.  
  1285.     waitBothBehaviour _ Behaviour block: [:slf :acq :com |
  1286.         (com name == #reply) ifTrue: [
  1287.             slf
  1288.                 becomes: waitOneBehaviour
  1289.                 withAquaintances: (Aquaintances
  1290.                     name: #replyTo mailAddress: (acq name: #replyTo)
  1291.                     name: #first mailAddress: (com at: 1))]].
  1292.  
  1293.     waitOneBehaviour _ Behaviour block: [:slf :acq :com |
  1294.         (com name == #reply) ifTrue: [
  1295.             (acq name: #replyTo)
  1296.                 sendMessage: #reply
  1297.                 with: ((acq name: #first) * (com at: 1))]].
  1298.  
  1299.     sink _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1300.         (com name == #reply)
  1301.             ifTrue: [
  1302.                 ActorTranscript sendMessage: #cr.
  1303.                 ActorTranscript sendMessage: #show with: (com at: 1) printString]]).
  1304.  
  1305.     (Actor
  1306.         withBehaviour: rangeBehaviour
  1307.         withAquaintances: (Aquaintances name: #replyTo mailAddress: sink))
  1308.             sendMessage: #factorial with: 1 with: 20
  1309.  
  1310.     "!
  1311.  
  1312. exampleWorkspace14
  1313.     "Select and execute the expressions here to run a timed version of the
  1314.      divide-and-conquor factorial example.  This is based on the code on page 45
  1315.      of 'Object Oriented Concurrent Programming'."
  1316.  
  1317.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1318.     ActorTextCollector open.        "Open a view on the actor transcript."
  1319.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1320.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1321.  
  1322.     "This bit creates a global actor capable of timing."
  1323.     "
  1324.     Smalltalk at: #ActorTimer put:
  1325.         (Actor withBehaviour:
  1326.             (Behaviour block: [:slf :acq :com |
  1327.                 (com name == #now) ifTrue: [
  1328.                     (com at: 1)
  1329.                         sendMessage: #reply
  1330.                         withArguments: (Time dateAndTimeNow)].
  1331.                 (com name == #milliseconds) ifTrue: [
  1332.                     (com at: 1)
  1333.                         sendMessage: #reply
  1334.                         with: (Time millisecondClockValue)]])).
  1335.     "
  1336.     "This bit finds the time taken for 'null' activity."
  1337.     "
  1338.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  1339.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1340.         (com name == #start) ifTrue: [
  1341.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1342.             slf becomes: secondBehaviour]].
  1343.  
  1344.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1345.         (com name == #reply) ifTrue: [
  1346.  
  1347.             slf mailAddress sendMessage: #reply with: 1.
  1348.  
  1349.             slf
  1350.                 becomes: thirdBehaviour
  1351.                 withAquaintances: (Aquaintances
  1352.                     name: #startTime mailAddress: (com at: 1))]].
  1353.  
  1354.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1355.         (com name == #reply) ifTrue: [
  1356.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1357.             slf becomes: fourthBehaviour]].
  1358.  
  1359.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1360.         (com name == #reply) ifTrue: [
  1361.             ActorTranscript sendMessage: #cr.
  1362.             ActorTranscript
  1363.                 sendMessage: #show
  1364.                 with: 'Time taken for no activity was: '.
  1365.             ActorTranscript sendMessage: #show with:
  1366.                 ((com at: 1) - (acq name: #startTime)) printString.
  1367.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1368.  
  1369.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1370.     "
  1371.     "This bit actually runs the factorial."
  1372.     "
  1373.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  1374.       rangeBehaviour mid waitBothBehaviour waitOneBehaviour sink |
  1375.  
  1376.     rangeBehaviour _ Behaviour block: [:slf :acq :com |
  1377.         (com name == #factorial) ifTrue: [
  1378.             ((com at: 1) = (com at: 2)) ifTrue: [
  1379.                 (acq name: #replyTo) sendMessage: #reply with: (com at: 1)].
  1380.             ((com at: 1) > (com at: 2)) ifTrue: [
  1381.                 (acq name: #replyTo) sendMessage: #reply with: 1].
  1382.             ((com at: 1) < (com at: 2)) ifTrue: [
  1383.                 slf becomes: waitBothBehaviour.
  1384.                 mid _ ((com at: 1) + (com at: 2)) // 2.
  1385.                 (Actor
  1386.                     withBehaviour: rangeBehaviour
  1387.                     withAquaintances: (Aquaintances
  1388.                         name: #replyTo mailAddress: slf mailAddress))
  1389.                             sendMessage: #factorial with: (com at: 1) with: mid.
  1390.                 (Actor
  1391.                     withBehaviour: rangeBehaviour
  1392.                     withAquaintances: (Aquaintances
  1393.                         name: #replyTo mailAddress: slf mailAddress))
  1394.                             sendMessage: #factorial with: (mid + 1) with: (com at: 2)]]].
  1395.  
  1396.     waitBothBehaviour _ Behaviour block: [:slf :acq :com |
  1397.         (com name == #reply) ifTrue: [
  1398.             slf
  1399.                 becomes: waitOneBehaviour
  1400.                 withAquaintances: (Aquaintances
  1401.                     name: #replyTo mailAddress: (acq name: #replyTo)
  1402.                     name: #first mailAddress: (com at: 1))]].
  1403.  
  1404.     waitOneBehaviour _ Behaviour block: [:slf :acq :com |
  1405.         (com name == #reply) ifTrue: [
  1406.             (acq name: #replyTo)
  1407.                 sendMessage: #reply
  1408.                 with: ((acq name: #first) * (com at: 1))]].
  1409.  
  1410.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1411.         (com name == #start) ifTrue: [
  1412.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1413.             slf becomes: secondBehaviour]].
  1414.  
  1415.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1416.         (com name == #reply) ifTrue: [
  1417.             (Actor
  1418.                 withBehaviour: rangeBehaviour
  1419.                 withAquaintances: (Aquaintances
  1420.                     name: #replyTo
  1421.                     mailAddress: slf mailAddress))
  1422.                 sendMessage: #factorial with: 1 with: 20.
  1423.             slf
  1424.                 becomes: thirdBehaviour
  1425.                 withAquaintances: (Aquaintances
  1426.                     name: #startTime mailAddress: (com at: 1))]].
  1427.  
  1428.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1429.         (com name == #reply) ifTrue: [
  1430.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1431.             slf becomes: fourthBehaviour]].
  1432.  
  1433.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1434.         (com name == #reply) ifTrue: [
  1435.             ActorTranscript sendMessage: #cr.
  1436.             ActorTranscript
  1437.                 sendMessage: #show
  1438.                 with: 'Time taken for factorial (20) was: '.
  1439.             ActorTranscript sendMessage: #show with:
  1440.                 ((com at: 1) - (acq name: #startTime)) printString.
  1441.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1442.  
  1443.  
  1444.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1445.  
  1446.     "!
  1447.  
  1448. exampleWorkspace2
  1449.     "Select and execute the expressions here to run the forwarder example."
  1450.  
  1451.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1452.     ActorTextCollector open.        "Open a view on the actor transcript."
  1453.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1454.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1455.     "
  1456.  
  1457.     | forwarder |
  1458.     forwarder _ Actor
  1459.             withBehaviour: (Behaviour
  1460.                 block: [:slf :acq :com |
  1461.                     (acq name: #link) sendCommunication: com])
  1462.             withAquaintances: (Aquaintances
  1463.                 name: #link
  1464.                 mailAddress: ActorTranscript).
  1465.     forwarder sendMessage: #clear.
  1466.     forwarder sendMessage: #show with: 'Hello, once again!!'.
  1467.     "!
  1468.  
  1469. exampleWorkspace3
  1470.     "Select and execute the expressions here to run the stack example."
  1471.  
  1472.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1473.     ActorTextCollector open.        "Open a view on the actor transcript."
  1474.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1475.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1476.     "
  1477.  
  1478.     | forwarderBehaviour stackBehaviour stackItemBehaviour sink stack |
  1479.     forwarderBehaviour _ Behaviour block: [:slf :acq :com |
  1480.         acq name: #link sendCommunication: com].
  1481.  
  1482.     stackBehaviour _ Behaviour block: [:slf :acq :com |
  1483.         (com name == #pop) & (acq name: #content) notNil ifTrue: [
  1484.             slf
  1485.                 becomes: forwarderBehaviour
  1486.                 withAquaintances: (Aquaintances
  1487.                     name: #link
  1488.                     mailAddress: (acq name: #link)).
  1489.             (com at: 1)
  1490.                 sendMessage: #contents
  1491.                 with: (acq name: #content)].
  1492.         (com name == #push) ifTrue: [
  1493.                 slf
  1494.                     becomes: stackBehaviour
  1495.                     withAquaintances: (Aquaintances
  1496.                             name: #link mailAddress: (Actor
  1497.                                 withBehaviour: stackBehaviour
  1498.                                 withAquaintances: (Aquaintances
  1499.                                     name: #link mailAddress: (acq name: #link)
  1500.                                     name: #content mailAddress: (acq name: #content)))
  1501.                             name: #content mailAddress: (com at: 1))]].
  1502.  
  1503.     stackItemBehaviour _ Behaviour block: [:slf :acq :com |
  1504.         (com name == #show)
  1505.             ifTrue: [
  1506.                 ActorTranscript sendMessage: #cr.
  1507.                 ActorTranscript sendMessage: #show with: 'Stack item: '.
  1508.                 ActorTranscript sendMessage: #show with: (acq name: #count) printString]].
  1509.  
  1510.     sink _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1511.         (com name == #contents)
  1512.             ifTrue: [
  1513.                 (com at: 1) sendMessage: #show]]).
  1514.  
  1515.     stack _ Actor withBehaviour: stackBehaviour withAquaintances: (
  1516.         Aquaintances
  1517.                 name: #content mailAddress: nil
  1518.                 name: #link mailAddress: nil).
  1519.  
  1520.     ActorTranscript sendMessage: #clear.
  1521.     stack
  1522.         sendMessage: #push
  1523.         with: (Actor
  1524.             withBehaviour: stackItemBehaviour
  1525.             withAquaintances: (Aquaintances name: #count mailAddress: 1)).
  1526.     stack
  1527.         sendMessage: #push
  1528.         with: (Actor
  1529.             withBehaviour: stackItemBehaviour
  1530.             withAquaintances: (Aquaintances name: #count mailAddress: 2)).
  1531.  
  1532.     stack sendMessage: #pop with: sink.
  1533.  
  1534.     stack
  1535.         sendMessage: #push
  1536.         with: (Actor
  1537.             withBehaviour: stackItemBehaviour
  1538.             withAquaintances: (Aquaintances name: #count mailAddress: 3)).
  1539.  
  1540.     stack sendMessage: #pop with: sink.
  1541.     stack sendMessage: #pop with: sink.
  1542.  
  1543.     "!
  1544.  
  1545. exampleWorkspace4
  1546.     "Select and execute the expressions here to run the simple recursive
  1547.      factorial example."
  1548.  
  1549.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1550.     ActorTextCollector open.        "Open a view on the actor transcript."
  1551.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1552.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1553.     "
  1554.  
  1555.     | recFactorial customer recCustomer factorialActor resultActor |
  1556.     recFactorial _ Behaviour block: [:slf :acq :com |
  1557.         (com name == #factorial) ifTrue: [
  1558.             slf becomes: recFactorial.
  1559.             (com at: 1) = 0
  1560.                 ifTrue: [
  1561.                     (com at: 2) sendMessage: #result with: 1]
  1562.                 ifFalse: [
  1563.                     customer _ Actor
  1564.                         withBehaviour: recCustomer
  1565.                         withAquaintances: (Aquaintances
  1566.                             name: #n mailAddress: (com at: 1)
  1567.                             name: #replyTo mailAddress: (com at: 2)).
  1568.                     slf mailAddress
  1569.                         sendMessage: #factorial
  1570.                         with: ((com at: 1) - 1)
  1571.                         with: customer]]].
  1572.  
  1573.     recCustomer _ Behaviour block: [:slf :acq :com |
  1574.         (com name == #result) ifTrue: [
  1575.             (acq name: #replyTo)
  1576.                 sendMessage: #result
  1577.                 with: ((acq name: #n) * (com at: 1))]].
  1578.  
  1579.     resultActor _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1580.         (com name == #result) ifTrue: [
  1581.             ActorTranscript sendMessage: #clear.
  1582.             ActorTranscript
  1583.                 sendMessage: #show
  1584.                 with: (com at: 1) printString]]).
  1585.  
  1586.     factorialActor _ Actor withBehaviour: recFactorial.
  1587.     factorialActor sendMessage: #factorial with: 3 with: resultActor.
  1588.  
  1589.     "!
  1590.  
  1591. exampleWorkspace5
  1592.     "Select and execute the expressions here to run another simple recursive
  1593.      factorial example."
  1594.  
  1595.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1596.     ActorTextCollector open.        "Open a view on the actor transcript."
  1597.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1598.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1599.     "
  1600.  
  1601.     | recFactorial recCustomer factorialActor resultActor |
  1602.     recFactorial _ Behaviour block: [:slf :acq :com |
  1603.         (com name == #factorial) ifTrue: [
  1604.             slf becomes: recFactorial.
  1605.             (com at: 1) = 0
  1606.                 ifTrue: [
  1607.                     (com at: 2) sendMessage: #reply with: 1]
  1608.                 ifFalse: [
  1609.                     slf mailAddress
  1610.                         sendMessage: #factorial
  1611.                         with: ((com at: 1) - 1)
  1612.                         with: (Actor
  1613.                             withBehaviour: recCustomer
  1614.                             withAquaintances: (Aquaintances
  1615.                                 name: #n mailAddress: (com at: 1)
  1616.                                 name: #replyTo mailAddress: (com at: 2)))]]].
  1617.  
  1618.     recCustomer _ Behaviour block: [:slf :acq :com |
  1619.         (com name == #reply) ifTrue: [
  1620.             (acq name: #replyTo)
  1621.                 sendMessage: #reply
  1622.                 with: ((acq name: #n) * (com at: 1))]].
  1623.  
  1624.     resultActor _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1625.         (com name == #reply) ifTrue: [
  1626.             ActorTranscript sendMessage: #clear.
  1627.             ActorTranscript
  1628.                 sendMessage: #show
  1629.                 with: (com at: 1) printString]]).
  1630.  
  1631.     factorialActor _ Actor withBehaviour: recFactorial.
  1632.     factorialActor sendMessage: #factorial with: 20 with: resultActor
  1633.     "!
  1634.  
  1635. exampleWorkspace6
  1636.     "Select and execute the expressions here to run a timer example."
  1637.  
  1638.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1639.     ActorTextCollector open.        "Open a view on the actor transcript."
  1640.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1641.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1642.  
  1643.     "This bit creates a global actor capable of timing."
  1644.     "
  1645.     Smalltalk at: #ActorTimer put:
  1646.         (Actor withBehaviour:
  1647.             (Behaviour block: [:slf :acq :com |
  1648.                 (com name == #now) ifTrue: [
  1649.                     (com at: 1)
  1650.                         sendMessage: #reply
  1651.                         withArguments: (Time dateAndTimeNow)].
  1652.                 (com name == #milliseconds) ifTrue: [
  1653.                     (com at: 1)
  1654.                         sendMessage: #reply
  1655.                         with: (Time millisecondClockValue)]])).
  1656.     "
  1657.     "This bit prints the date and time on the Actor Transcript."
  1658.     "
  1659.     | resultActor |
  1660.     resultActor _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1661.         (com name == #reply) ifTrue: [
  1662.             ActorTranscript sendMessage: #clear.
  1663.             ActorTranscript
  1664.                 sendMessage: #show
  1665.                 with: (com at: 1) printString, '  ', (com at: 2) printString]]).
  1666.  
  1667.     ActorTimer sendMessage: #now with: resultActor.
  1668.     "!
  1669.  
  1670. exampleWorkspace7
  1671.     "Select and execute the expressions here to run another timer example."
  1672.  
  1673.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1674.     ActorTextCollector open.        "Open a view on the actor transcript."
  1675.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1676.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1677.  
  1678.     "This bit creates a global actor capable of timing."
  1679.     "
  1680.     Smalltalk at: #ActorTimer put:
  1681.         (Actor withBehaviour:
  1682.             (Behaviour block: [:slf :acq :com |
  1683.                 (com name == #now) ifTrue: [
  1684.                     (com at: 1)
  1685.                         sendMessage: #reply
  1686.                         withArguments: (Time dateAndTimeNow)].
  1687.                 (com name == #milliseconds) ifTrue: [
  1688.                     (com at: 1)
  1689.                         sendMessage: #reply
  1690.                         with: (Time millisecondClockValue)]])).
  1691.     "
  1692.     "This bit displays the millisecond clock on the Actor Transcript."
  1693.     "
  1694.     | resultActor |
  1695.     resultActor _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1696.         (com name == #reply) ifTrue: [
  1697.             ActorTranscript sendMessage: #cr.
  1698.             ActorTranscript
  1699.                 sendMessage: #show
  1700.                 with: (com at: 1) printString]]).
  1701.  
  1702.     ActorTimer sendMessage: #milliseconds with: resultActor.
  1703.     "!
  1704.  
  1705. exampleWorkspace8
  1706.     "Select and execute the expressions here to run a timed simple recursive
  1707.      factorial example."
  1708.  
  1709.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1710.     ActorTextCollector open.        "Open a view on the actor transcript."
  1711.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1712.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1713.  
  1714.     "This bit creates a global actor capable of timing."
  1715.     "
  1716.     Smalltalk at: #ActorTimer put:
  1717.         (Actor withBehaviour:
  1718.             (Behaviour block: [:slf :acq :com |
  1719.                 (com name == #now) ifTrue: [
  1720.                     (com at: 1)
  1721.                         sendMessage: #reply
  1722.                         withArguments: (Time dateAndTimeNow)].
  1723.                 (com name == #milliseconds) ifTrue: [
  1724.                     (com at: 1)
  1725.                         sendMessage: #reply
  1726.                         with: (Time millisecondClockValue)]])).
  1727.     "
  1728.     "This bit finds the time taken for 'null' activity."
  1729.     "
  1730.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  1731.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1732.         (com name == #start) ifTrue: [
  1733.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1734.             slf becomes: secondBehaviour]].
  1735.  
  1736.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1737.         (com name == #reply) ifTrue: [
  1738.  
  1739.             slf mailAddress sendMessage: #reply with: 1.
  1740.  
  1741.             slf
  1742.                 becomes: thirdBehaviour
  1743.                 withAquaintances: (Aquaintances
  1744.                     name: #startTime mailAddress: (com at: 1))]].
  1745.  
  1746.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1747.         (com name == #reply) ifTrue: [
  1748.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1749.             slf becomes: fourthBehaviour]].
  1750.  
  1751.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1752.         (com name == #reply) ifTrue: [
  1753.             ActorTranscript sendMessage: #cr.
  1754.             ActorTranscript
  1755.                 sendMessage: #show
  1756.                 with: 'Time taken for no activity was: '.
  1757.             ActorTranscript sendMessage: #show with:
  1758.                 ((com at: 1) - (acq name: #startTime)) printString.
  1759.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1760.  
  1761.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1762.     "
  1763.     "This bit actually times the factorial."
  1764.     "
  1765.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  1766.       recFactorial recCustomer |
  1767.  
  1768.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1769.         (com name == #start) ifTrue: [
  1770.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1771.             slf becomes: secondBehaviour]].
  1772.  
  1773.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1774.         (com name == #reply) ifTrue: [
  1775.             (Actor withBehaviour: recFactorial)
  1776.                 sendMessage: #factorial with: 20 with: slf mailAddress.
  1777.             slf
  1778.                 becomes: thirdBehaviour
  1779.                 withAquaintances: (Aquaintances
  1780.                     name: #startTime mailAddress: (com at: 1))]].
  1781.  
  1782.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1783.         (com name == #reply) ifTrue: [
  1784.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1785.             slf becomes: fourthBehaviour]].
  1786.  
  1787.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1788.         (com name == #reply) ifTrue: [
  1789.             ActorTranscript sendMessage: #cr.
  1790.             ActorTranscript
  1791.                 sendMessage: #show
  1792.                 with: 'Time taken for factorial (20) was: '.
  1793.             ActorTranscript sendMessage: #show with:
  1794.                 ((com at: 1) - (acq name: #startTime)) printString.
  1795.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1796.  
  1797.     recFactorial _ Behaviour block: [:slf :acq :com |
  1798.         (com name == #factorial) ifTrue: [
  1799.             slf becomes: recFactorial.
  1800.             (com at: 1) = 0
  1801.                 ifTrue: [
  1802.                     (com at: 2) sendMessage: #reply with: 1]
  1803.                 ifFalse: [
  1804.                     slf mailAddress
  1805.                         sendMessage: #factorial
  1806.                         with: ((com at: 1) - 1)
  1807.                         with: (Actor
  1808.                             withBehaviour: recCustomer
  1809.                             withAquaintances: (Aquaintances
  1810.                                 name: #n mailAddress: (com at: 1)
  1811.                                 name: #replyTo mailAddress: (com at: 2)))]]].
  1812.  
  1813.     recCustomer _ Behaviour block: [:slf :acq :com |
  1814.         (com name == #reply) ifTrue: [
  1815.             (acq name: #replyTo)
  1816.                 sendMessage: #reply
  1817.                 with: ((acq name: #n) * (com at: 1))]].
  1818.  
  1819.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1820.     "!
  1821.  
  1822. exampleWorkspace9
  1823.     "Select and execute the expressions here to run a fibonacci example."
  1824.  
  1825.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1826.     ActorTextCollector open.        "Open a view on the actor transcript."
  1827.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1828.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1829.  
  1830.      "
  1831.     | fibonacciBehaviour waitBothBehaviour waitOneBehaviour sink |
  1832.  
  1833.     fibonacciBehaviour _ Behaviour block: [:slf :acq :com |
  1834.         (com name == #fibonacci) ifTrue: [
  1835.             ((com at: 1) <= 1)
  1836.                 ifTrue: [
  1837.                     (acq name: #replyTo) sendMessage: #reply with: (com at: 1)]
  1838.                 ifFalse: [
  1839.                     slf becomes: waitBothBehaviour.
  1840.                     (Actor
  1841.                         withBehaviour: fibonacciBehaviour
  1842.                         withAquaintances: (Aquaintances
  1843.                             name: #replyTo
  1844.                             mailAddress: slf mailAddress))
  1845.                                 sendMessage: #fibonacci
  1846.                                 with: ((com at: 1) - 1).
  1847.                     (Actor
  1848.                         withBehaviour: fibonacciBehaviour
  1849.                         withAquaintances: (Aquaintances
  1850.                             name: #replyTo
  1851.                             mailAddress: slf mailAddress))
  1852.                                 sendMessage: #fibonacci
  1853.                                 with: ((com at: 1) - 2)]]].
  1854.  
  1855.     waitBothBehaviour _ Behaviour block: [:slf :acq :com |
  1856.         (com name == #reply) ifTrue: [
  1857.             slf
  1858.                 becomes: waitOneBehaviour
  1859.                 withAquaintances: (Aquaintances
  1860.                     name: #replyTo mailAddress: (acq name: #replyTo)
  1861.                     name: #first mailAddress: (com at: 1))]].
  1862.  
  1863.     waitOneBehaviour _ Behaviour block: [:slf :acq :com |
  1864.         (com name == #reply) ifTrue: [
  1865.             (acq name: #replyTo)
  1866.                 sendMessage: #reply
  1867.                 with: ((acq name: #first) + (com at: 1))]].
  1868.  
  1869.     sink _ Actor withBehaviour: (Behaviour block: [:slf :acq :com |
  1870.         (com name == #reply)
  1871.             ifTrue: [
  1872.                 ActorTranscript sendMessage: #cr.
  1873.                 ActorTranscript sendMessage: #show with: (com at: 1) printString]]).
  1874.  
  1875.     (Actor
  1876.         withBehaviour: fibonacciBehaviour
  1877.         withAquaintances: (Aquaintances name: #replyTo mailAddress: sink))
  1878.             sendMessage: #fibonacci with: 13.
  1879.  
  1880.     "! !
  1881.  
  1882. Actor initialize!
  1883.  
  1884.  
  1885. ActorModel subclass: #Behaviour
  1886.     instanceVariableNames: 'block '
  1887.     classVariableNames: ''
  1888.     poolDictionaries: ''
  1889.     category: 'Actors-Simulation'!
  1890. Behaviour comment:
  1891. 'I represent the current activity of an actor.  My instance variable:
  1892.  
  1893. block    <BlockContext> which is activated when the actor receives a
  1894.         task.  The block expects three arguments, representing `slf'' (the
  1895.         actor receiving the task), `acq'' (the aquaintances of the actor,
  1896.         and `com'' the communication in the present task.'!
  1897.  
  1898.  
  1899. !Behaviour methodsFor: 'initialize-release'!
  1900.  
  1901. release
  1902.     "Release the instance variable."
  1903.  
  1904.     block release.
  1905.     super release! !
  1906.  
  1907. !Behaviour methodsFor: 'accessing'!
  1908.  
  1909. block
  1910.     "Answer with the block describing the behaviour of the receiver."
  1911.  
  1912.     ^block!
  1913.  
  1914. block: aBlock
  1915.     "Make the activity of the receiver aBlock."
  1916.  
  1917.     block _ aBlock.
  1918.     self changed: #all! !
  1919.  
  1920. !Behaviour methodsFor: 'printing'!
  1921.  
  1922. printOn: aStream
  1923.     "Put a printable representation of the receiver on aStream."
  1924.  
  1925.     self class name printOn: aStream! !
  1926. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1927.  
  1928. Behaviour class
  1929.     instanceVariableNames: ''!
  1930.  
  1931.  
  1932. !Behaviour class methodsFor: 'instance creation'!
  1933.  
  1934. block: aBlock
  1935.     "Create a new instance of the receiver, with activity called aSymbol
  1936.      as described by aBlock."
  1937.  
  1938.     ^self new block: aBlock! !
  1939.  
  1940. ActorModel subclass: #Tag
  1941.     instanceVariableNames: ''
  1942.     classVariableNames: ''
  1943.     poolDictionaries: ''
  1944.     category: 'Actors-Simulation'!
  1945. Tag comment:
  1946. 'I represent a unique identifier used to identify a Task.  Tags do not change.'!
  1947.  
  1948.  
  1949. !Tag methodsFor: 'accessing'!
  1950.  
  1951. value
  1952.     "Answer with the unique identifier represented by the receiver."
  1953.  
  1954.     ^self asOop! !
  1955.  
  1956. !Tag methodsFor: 'printing'!
  1957.  
  1958. printOn: aStream
  1959.     "Put a printable representation of the receiver on aStream."
  1960.  
  1961.     aStream nextPutAll: self value printString! !
  1962.  
  1963. ActorModel subclass: #Communication
  1964.     instanceVariableNames: 'name arguments '
  1965.     classVariableNames: ''
  1966.     poolDictionaries: ''
  1967.     category: 'Actors-Simulation'!
  1968. Communication comment:
  1969. 'I represent the content of a message (Task) sent from one Actor to
  1970. another.  Communications do not change.  My instance variables are:
  1971.  
  1972. name        <Symbol> identifying the operation intended.
  1973.  
  1974. arguments    <Array> of arguments to the operation.'!
  1975.  
  1976.  
  1977. !Communication methodsFor: 'initialize-release'!
  1978.  
  1979. release
  1980.     "Release all my instance variables."
  1981.  
  1982.     name release.
  1983.     arguments release.
  1984.     super release! !
  1985.  
  1986. !Communication methodsFor: 'accessing'!
  1987.  
  1988. at: index
  1989.     "Answer with the argument at index in the argument list."
  1990.  
  1991.     ^arguments at: index!
  1992.  
  1993. name
  1994.     "Answer with the name of the receiver."
  1995.  
  1996.     ^name! !
  1997.  
  1998. !Communication methodsFor: 'printing'!
  1999.  
  2000. printOn: aStream
  2001.     "Put a printable representation of the receiver on aStream."
  2002.  
  2003.     self class name printOn: aStream.
  2004.     aStream nextPutAll: ' called '.
  2005.     name printString printOn: aStream.! !
  2006.  
  2007. !Communication methodsFor: 'inspecting'!
  2008.  
  2009. labelString
  2010.     "Answer with a string suitable for use as a view's label."
  2011.  
  2012.     ^name printString! !
  2013.  
  2014. !Communication methodsFor: 'private'!
  2015.  
  2016. setArguments: anArray
  2017.     "Set the arguments of the receiver to anArray."
  2018.  
  2019.     arguments _ anArray!
  2020.  
  2021. setName: aSymbol
  2022.     "Set the name of the receiver to aSymbol."
  2023.  
  2024.     name _ aSymbol! !
  2025. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2026.  
  2027. Communication class
  2028.     instanceVariableNames: ''!
  2029.  
  2030.  
  2031. !Communication class methodsFor: 'instance creation'!
  2032.  
  2033. name: aSymbol
  2034.     "Create a new instance of the receiver, with name aSymbol and
  2035.      no arguments."
  2036.  
  2037.     ^self name: aSymbol withArguments: #()!
  2038.  
  2039. name: aSymbol with: anArgument
  2040.     "Create a new instance of the receiver, with name aSymbol and
  2041.      one argument."
  2042.  
  2043.     ^self name: aSymbol withArguments: (Array with: anArgument)!
  2044.  
  2045. name: aSymbol with: firstArgument with: secondArgument
  2046.     "Create a new instance of the receiver, with name aSymbol and
  2047.      two arguments."
  2048.  
  2049.     ^self
  2050.         name: aSymbol
  2051.         withArguments: (Array with: firstArgument with: secondArgument)!
  2052.  
  2053. name: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  2054.     "Create a new instance of the receiver, with name aSymbol and
  2055.      three arguments."
  2056.  
  2057.     ^self
  2058.         name: aSymbol
  2059.         withArguments: (Array
  2060.                             with: firstArgument
  2061.                             with: secondArgument
  2062.                             with: thirdArgument)!
  2063.  
  2064. name: aSymbol withArguments: anArray
  2065.     "Create a new instance of the receiver, with name aSymbol and
  2066.      arguments in anArray."
  2067.  
  2068.     | temp |
  2069.     temp _ self new setName: aSymbol.
  2070.     temp setArguments: anArray.
  2071.     ^temp! !
  2072.  
  2073. ActorModel subclass: #MailQueue
  2074.     instanceVariableNames: 'contents '
  2075.     classVariableNames: ''
  2076.     poolDictionaries: ''
  2077.     category: 'Actors-Simulation'!
  2078. MailQueue comment:
  2079. 'I represent a queue of messages (Tasks) sent to an actor waiting to
  2080. be processed.  An instance of me is associated with every actor.  If an
  2081. actor''s mail queue is empty, it is said to be inactive.  My instance variables:
  2082.  
  2083. contents    <ActorCollection> of Tasks, possibly empty.'!
  2084.  
  2085.  
  2086. !MailQueue methodsFor: 'initialize-release'!
  2087.  
  2088. initialize
  2089.     "Initialize the instance variable."
  2090.  
  2091.     contents _ ActorCollection new!
  2092.  
  2093. release
  2094.     "Release all my instance variables."
  2095.  
  2096.     contents release.
  2097.     super release! !
  2098.  
  2099. !MailQueue methodsFor: 'adding'!
  2100.  
  2101. addMessage: aTask
  2102.     "Add the message aTask to the end of queue represented by
  2103.      the receiver."
  2104.  
  2105.     contents addLast: aTask.
  2106.     self changed: #all! !
  2107.  
  2108. !MailQueue methodsFor: 'removing'!
  2109.  
  2110. getMessage
  2111.     "Answer with the first message (Task) in the receiver, or nil, if
  2112.      there is no message available."
  2113.  
  2114.     | message |
  2115.     contents isEmpty ifFalse: [
  2116.         message _ contents removeFirst.
  2117.         self changed: #all].
  2118.     ^message! !
  2119.  
  2120. !MailQueue methodsFor: 'testing'!
  2121.  
  2122. isEmpty
  2123.     "Answer whether the mail queue represented by the receiver is
  2124.      empty or not."
  2125.  
  2126.     ^contents isEmpty! !
  2127.  
  2128. !MailQueue methodsFor: 'printing'!
  2129.  
  2130. printOn: aStream
  2131.     "Put a printable representation of the receiver on aStream."
  2132.  
  2133.     self class name printOn: aStream.
  2134.     aStream nextPutAll: ' (', contents size printString, ')'! !
  2135. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2136.  
  2137. MailQueue class
  2138.     instanceVariableNames: ''!
  2139.  
  2140.  
  2141. !MailQueue class methodsFor: 'instance creation'!
  2142.  
  2143. new
  2144.     "Answer with a new initialized instance of the receiver."
  2145.  
  2146.     ^super new initialize! !
  2147.  
  2148. ActorModel subclass: #Task
  2149.     instanceVariableNames: 'tag target communication '
  2150.     classVariableNames: ''
  2151.     poolDictionaries: ''
  2152.     category: 'Actors-Simulation'!
  2153. Task comment:
  2154. 'I represent a message sent from one actor to another.
  2155.  
  2156. My instance variables are:
  2157.  
  2158. tag                <Tag> unique identifier for this message.
  2159.  
  2160. target            <MailAddress> of the destination actor.
  2161.  
  2162. communication    <Communication> contents of the message.'!
  2163.  
  2164.  
  2165. !Task methodsFor: 'initialize-release'!
  2166.  
  2167. initialize
  2168.     "Initialize the tag instance variable."
  2169.  
  2170.     tag _ Tag new!
  2171.  
  2172. release
  2173.     "Release the receiver's tag and communication instance variables.  Nil
  2174.      out the receiver's target, to break up possible cycles."
  2175.  
  2176.     tag release.
  2177.     target _ nil.
  2178.     communication release.
  2179.     super release! !
  2180.  
  2181. !Task methodsFor: 'accessing'!
  2182.  
  2183. communication
  2184.     "Answer with the communication of the receiver.  Used only by the interpreter."
  2185.  
  2186.     ^communication!
  2187.  
  2188. target
  2189.     "Answer with the target mail address of the receiver.  Used only
  2190.      by the interpreter."
  2191.  
  2192.     ^target! !
  2193.  
  2194. !Task methodsFor: 'sending'!
  2195.  
  2196. send
  2197.     "Send the receiver to the target."
  2198.  
  2199.     target send: self! !
  2200.  
  2201. !Task methodsFor: 'printing'!
  2202.  
  2203. printOn: aStream
  2204.     "Put a printable representation of the receiver on aStream."
  2205.  
  2206.     | addr |
  2207.     addr _ target isNil ifTrue: ['nowhere'] ifFalse: [target printString].
  2208.     self class name printOn: aStream.
  2209.     aStream nextPutAll: ' ('.
  2210.     tag printOn: aStream.
  2211.     aStream nextPutAll: ') to ', addr! !
  2212.  
  2213. !Task methodsFor: 'private'!
  2214.  
  2215. setCommunication: aCommunication
  2216.     "Set the communication of the receiver to aCommunication."
  2217.  
  2218.     communication _ aCommunication!
  2219.  
  2220. setTarget: aMailAddress
  2221.     "Set the target mail address of the receiver to aMailAddress."
  2222.  
  2223.     target _ aMailAddress! !
  2224. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2225.  
  2226. Task class
  2227.     instanceVariableNames: ''!
  2228.  
  2229.  
  2230. !Task class methodsFor: 'instance creation'!
  2231.  
  2232. communication: aCommunication target: mailAddr
  2233.     "Answer with a new instance of the receiver, with communication
  2234.      given by aCommunication, and target mailAddr."
  2235.  
  2236.     | temp |
  2237.     temp _ self new setTarget: mailAddr.
  2238.     temp setCommunication: aCommunication.
  2239.     ^temp!
  2240.  
  2241. new
  2242.     "Answer with a new initialised instance of the receiver."
  2243.  
  2244.     ^super new initialize! !
  2245.  
  2246. MouseMenuController subclass: #ActorInterpreterController
  2247.     instanceVariableNames: ''
  2248.     classVariableNames: 'ActorYellowButtonMenu ActorYellowButtonMessages '
  2249.     poolDictionaries: ''
  2250.     category: 'Actors-Interpreter'!
  2251. ActorInterpreterController comment:
  2252. 'I represent a controller for a actor interpreter.  I support a yellow button
  2253. menu allowing the mode to be changed, and my model to be inspected in
  2254. various ways.'!
  2255.  
  2256.  
  2257. !ActorInterpreterController methodsFor: 'initialize-release'!
  2258.  
  2259. initialize
  2260.     "Set up the yellow button menu."
  2261.  
  2262.     super initialize.
  2263.     self yellowButtonMenu: ActorYellowButtonMenu 
  2264.         yellowButtonMessages: ActorYellowButtonMessages! !
  2265.  
  2266. !ActorInterpreterController methodsFor: 'control defaults'!
  2267.  
  2268. controlActivity
  2269.     "If the keyboard is pressed, then hand control to the corresponding
  2270.      subview.  Then, cause the model to execute one interpreter cycle,
  2271.      then continue as defined in the superclass."
  2272.  
  2273.     sensor keyboardPressed ifTrue: [self processKey].
  2274.     model runProcess.
  2275.     super controlActivity!
  2276.  
  2277. isControlActive
  2278.     "Answer true if the keyboard is pressed, or if control is active
  2279.      as defined in the superclass, and the blue button is not pressed.
  2280.      Otherwise, answer false."
  2281.  
  2282.     ^sensor keyboardPressed |
  2283.         super isControlActive & sensor blueButtonPressed not!
  2284.  
  2285. isControlWanted
  2286.     "Answer true if the cursor is inside the inset display box 
  2287.      of the receiver's view, or if the keyboard is pressed,
  2288.      and answer false, otherwise."
  2289.  
  2290.     ^sensor keyboardPressed | self viewHasCursor!
  2291.  
  2292. processKey
  2293.     "The user typed a key on the keyboard.  Give control to the subView that
  2294.     is selected by this key."
  2295.  
  2296.     | aView |
  2297.     aView _ view subViewContainingCharacter: sensor keyboard.
  2298.     aView notNil ifTrue: [aView controller sendMessage]! !
  2299.  
  2300. !ActorInterpreterController methodsFor: 'menu messages'!
  2301.  
  2302. auto
  2303.     "Set auto mode.  The model (interpreter) runs when the `run' button
  2304.      is pressed, regardless of whether control is over the view.  The interpreter stops
  2305.      when the queue becomes empty."
  2306.  
  2307.     self model stopWhenEmpty: false.
  2308.     self model auto: true.
  2309.     self model changed: #mode!
  2310.  
  2311. inspectFirst
  2312.     "Inspect the first actor on the active list, if any."
  2313.  
  2314.     model activeList isEmpty
  2315.         ifTrue: [view flash]
  2316.         ifFalse: [model activeList first inspect]!
  2317.  
  2318. inspectModel
  2319.     "Open an Inspector on the model (so that individual actors
  2320.      can be inspected)."
  2321.  
  2322.     self model activeList inspect!
  2323.  
  2324. manual
  2325.     "Set manual mode.  The model (interpreter) runs when the `run' button
  2326.      is pressed, and control is over the view.  The interpreter stops when
  2327.      the queue becomes empty."
  2328.  
  2329.     self model stopWhenEmpty: true.
  2330.     self model auto: false.
  2331.     self model changed: #mode!
  2332.  
  2333. normal
  2334.     "Set normal mode.  The model (interpreter) runs when the `run' button
  2335.      is pressed, and control is over the view.  The interpreter remains runnable
  2336.      when the queue becomes empty."
  2337.  
  2338.     self model stopWhenEmpty: false.
  2339.     self model auto: false.
  2340.     self model changed: #mode! !
  2341. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2342.  
  2343. ActorInterpreterController class
  2344.     instanceVariableNames: ''!
  2345.  
  2346.  
  2347. !ActorInterpreterController class methodsFor: 'class initialization'!
  2348.  
  2349. initialize
  2350.     "Initialize the menu class variables."
  2351.     "ActorInterpreterController initialize."
  2352.  
  2353.     ActorYellowButtonMenu _ PopUpMenu
  2354.         labels: 'auto\normal\manual\inspect\inspect first' withCRs
  2355.         lines: #(3).
  2356.     ActorYellowButtonMessages _ #(auto normal manual inspectModel inspectFirst).! !
  2357.  
  2358. ActorInterpreterController initialize!
  2359.  
  2360.  
  2361. View subclass: #ActorInterpreterView
  2362.     instanceVariableNames: 'stopButton goButton '
  2363.     classVariableNames: ''
  2364.     poolDictionaries: ''
  2365.     category: 'Actors-Interpreter'!
  2366. ActorInterpreterView comment:
  2367. 'I represent a view on an interpreter for actors.'!
  2368.  
  2369.  
  2370. !ActorInterpreterView methodsFor: 'subView access'!
  2371.  
  2372. subViewContainingCharacter: aCharacter
  2373.     "Answer the receiver's subView that corresponds to the key, aCharacter.
  2374.     Answer nil if no subView is selected by aCharacter."
  2375.  
  2376.     self subViews reverseDo: 
  2377.         [:aSubView |
  2378.         (aSubView containsKey: aCharacter) ifTrue: [^aSubView]].
  2379.     ^nil! !
  2380.  
  2381. !ActorInterpreterView methodsFor: 'updating'!
  2382.  
  2383. update: aParameter
  2384.     "If aParameter is #stopped, then toggle the halt button.  If
  2385.      aParameter is #run, then toggle the run button.  If aParameter
  2386.      is #release, then close the view."
  2387.  
  2388.     aParameter == #stopped ifTrue: [stopButton turnOn].
  2389.     aParameter == #run ifTrue: [goButton turnOn].
  2390.     aParameter == #release ifTrue: [self topView controller closeAndUnschedule]! !
  2391.  
  2392. !ActorInterpreterView methodsFor: 'private'!
  2393.  
  2394. insertButtonViews
  2395.     "Set up the button views for a new instance of the receiver."
  2396.  
  2397.     | stepView stopView runView connector |
  2398.     stepView _ SwitchView new model: (
  2399.         Button newOff onAction: [self model processOneActor]).
  2400.     stepView label: ('step' asDisplayText).
  2401.     stepView controller: IndicatorOnSwitchController new.
  2402.     stepView borderWidth: 2.
  2403.     stepView key: $s.
  2404.     self addSubView: stepView viewport: (20@100 extent: 40@28).
  2405.  
  2406.     connector _ Object new.        "Dummy object for connections."
  2407.     stopButton _ (OneOnSwitch newOff onAction: [self model stopProcessing]).
  2408.     stopButton connection: connector.
  2409.     stopView _ SwitchView new model: stopButton.
  2410.     stopView label: ('halt' asDisplayText).
  2411.     stopView borderWidth: 2.
  2412.     stopView key: $h.
  2413.     self addSubView: stopView viewport: (80@100 extent: 40@28).
  2414.  
  2415.     goButton _ (OneOnSwitch newOn onAction: [self model startProcessing]).
  2416.     goButton connection: connector.
  2417.     runView _ SwitchView new model: goButton.
  2418.     runView label: ('run' asDisplayText).
  2419.     runView borderWidth: 2.
  2420.     runView key: $r.
  2421.     self addSubView: runView viewport: (140@100 extent: 40@28).!
  2422.  
  2423. insertDisplayViews
  2424.     "Set up the display views for a new instance of the receiver."
  2425.  
  2426.     | actorView modeView |
  2427.     modeView _ ActorInterpreterModeView new.
  2428.     modeView controller: NoController new.
  2429.     modeView model: self model.
  2430.     modeView insideColor: Form white.
  2431.     modeView borderWidth: 2.
  2432.     self addSubView: modeView viewport: (20 @ 12 extent: 160 @ 32).
  2433.  
  2434.     actorView _ ActorInterpreterDisplayView new.
  2435.     actorView model: self model.
  2436.     actorView insideColor: Form white.
  2437.     actorView controller: NoController new.
  2438.     actorView borderWidth: 2.
  2439.     self addSubView: actorView viewport: (20 @ 50 extent: 160 @ 32)! !
  2440. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2441.  
  2442. ActorInterpreterView class
  2443.     instanceVariableNames: ''!
  2444.  
  2445.  
  2446. !ActorInterpreterView class methodsFor: 'instance creation'!
  2447.  
  2448. open
  2449.     "Create and schedule a view on the current Actor interpreter."
  2450.     "ActorInterpreterView open."
  2451.  
  2452.     self openOn: Actor interpreter!
  2453.  
  2454. openOn: anActorInterpreter
  2455.     "Create and schedule a view on anActorInterpreter."
  2456.     "ActorInterpreterView openOn: Actor interpreter."
  2457.  
  2458.     | topView view |
  2459.     topView _ StandardSystemView
  2460.                 model: nil
  2461.                 label: 'Actor Interpreter'
  2462.                 minimumSize: 200@150.
  2463.     topView insideColor: nil.
  2464.  
  2465.     view _ self new.
  2466.     view controller: ActorInterpreterController new.
  2467.     view model: anActorInterpreter.
  2468.     view insideColor: Form gray.
  2469.     view borderColor: Form black.
  2470.     view borderWidth: 1.
  2471.     topView
  2472.         addSubView: view
  2473.         window: (0@0 extent: 200@150)
  2474.         viewport: topView window.
  2475.  
  2476.     view insertButtonViews.
  2477.     view insertDisplayViews.
  2478.  
  2479.     topView controller open! !
  2480.  
  2481. View subclass: #ActorInterpreterDisplayView
  2482.     instanceVariableNames: 'displayedValue '
  2483.     classVariableNames: ''
  2484.     poolDictionaries: ''
  2485.     category: 'Actors-Interpreter'!
  2486. ActorInterpreterDisplayView comment:
  2487. 'I represent a display of the number of active actors in the model.'!
  2488.  
  2489.  
  2490. !ActorInterpreterDisplayView methodsFor: 'displaying'!
  2491.  
  2492. displayView
  2493.     "Display the number of actors on the model's list."
  2494.  
  2495.     displayedValue _ model size.
  2496.     ((displayedValue = 1)
  2497.         ifTrue: ['1 actor active']
  2498.         ifFalse: [self model size printString, ' actors active'])
  2499.             displayAt: (self insetDisplayBox topLeft + (10@6)).! !
  2500.  
  2501. !ActorInterpreterDisplayView methodsFor: 'updating'!
  2502.  
  2503. update: parameter
  2504.     "If the parameter is #activeActors, update the displayed
  2505.      value, provided that my topView is not collapsed."
  2506.  
  2507.     (displayedValue isNil or: [displayedValue ~= model size]) ifTrue: [
  2508.         self topView isCollapsed ifFalse: [
  2509.             self displaySafe: [self display]]]! !
  2510.  
  2511. !ActorInterpreterDisplayView methodsFor: 'subView access'!
  2512.  
  2513. containsKey: aCharacter
  2514.     "This view does not respond to any characters."
  2515.  
  2516.     ^false! !
  2517.  
  2518. View subclass: #ActorInterpreterModeView
  2519.     instanceVariableNames: ''
  2520.     classVariableNames: ''
  2521.     poolDictionaries: ''
  2522.     category: 'Actors-Interpreter'!
  2523. ActorInterpreterModeView comment:
  2524. 'I represent a display of the mode of the model.'!
  2525.  
  2526.  
  2527. !ActorInterpreterModeView methodsFor: 'displaying'!
  2528.  
  2529. displayView
  2530.     "Display the current mode."
  2531.  
  2532.     | stop |
  2533.     stop _ self model stopWhenEmpty.
  2534.     (Text
  2535.         string: (self model auto
  2536.             ifTrue: [stop ifTrue: ['Unknown mode'] ifFalse: ['Auto mode']]
  2537.             ifFalse: [stop ifTrue: ['Manual mode'] ifFalse: ['Normal mode']])
  2538.         emphasis: 2) asDisplayText displayAt: (self insetDisplayBox topLeft + (10@6))! !
  2539.  
  2540. !ActorInterpreterModeView methodsFor: 'subView access'!
  2541.  
  2542. containsKey: aCharacter
  2543.     "This view does not respond to any characters."
  2544.  
  2545.     ^false! !
  2546.  
  2547. !ActorInterpreterModeView methodsFor: 'updating'!
  2548.  
  2549. update: aParameter
  2550.     "If parameter is #mode, update the receiver's display.  Otherwise,
  2551.      do nothing."
  2552.  
  2553.     aParameter == #mode ifTrue: [    self display]! 
  2554.  
  2555. !StandardSystemController subclass: #SMACKInspectorController
  2556.     instanceVariableNames: ''
  2557.     classVariableNames: ''
  2558.     poolDictionaries: ''
  2559.     category: 'Actors-Inspectors'!
  2560. SMACKInspectorController comment:
  2561. 'I am a special kind of InspectorController which knows to how to remove
  2562. dependents before closing.'!
  2563.  
  2564.  
  2565. !SMACKInspectorController methodsFor: 'scheduling'!
  2566.  
  2567. close
  2568.     "Remove the dependency between the model's object and the
  2569.      model before closing."
  2570.  
  2571.     model object removeDependent: model.
  2572.     super close! !
  2573.  
  2574. InspectorView subclass: #SMACKInspectorView
  2575.     instanceVariableNames: ''
  2576.     classVariableNames: ''
  2577.     poolDictionaries: ''
  2578.     category: 'Actors-Inspectors'!
  2579. SMACKInspectorView comment:
  2580. 'I represent a view on a special Inspector for Actor simulations.  I
  2581. change my visible state when my model is updated, and can close
  2582. and unschedule myself when the object being inspected is no longer
  2583. required.  I also support active icons.'!
  2584.  
  2585.  
  2586. !SMACKInspectorView methodsFor: 'updating'!
  2587.  
  2588. update: aParameter
  2589.     "If aParameter is #all, redisplay the view.  If aParameter is
  2590.     #release, remove the view. Otherwise do nothing."
  2591.  
  2592.     aParameter == #all ifTrue: [
  2593.         ^self displaySafe: [
  2594.             self isCollapsed ifFalse: [
  2595.                 model changed: #field.
  2596.                 model changed: #text].
  2597.             self newLabel: model object labelString]].
  2598.     aParameter == #release ifTrue: [controller closeAndUnschedule]! !
  2599. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2600.  
  2601. SMACKInspectorView class
  2602.     instanceVariableNames: ''!
  2603.  
  2604.  
  2605. !SMACKInspectorView class methodsFor: 'private'!
  2606.  
  2607. buildScheduledView: anInspector 
  2608.     | topView |
  2609.     topView _ self
  2610.                 model: anInspector
  2611.                 label: anInspector object labelString
  2612.                 minimumSize: 180 @ 120.
  2613.     topView controller: SMACKInspectorController new.
  2614.     topView icon: (Icon constantNamed: #actor).
  2615.     self
  2616.         view: anInspector
  2617.         in: (0 @ 0 extent: 1 @ 1)
  2618.         of: topView.
  2619.     ^topView! !
  2620.  
  2621. Inspector subclass: #SMACKInspector
  2622.     instanceVariableNames: ''
  2623.     classVariableNames: ''
  2624.     poolDictionaries: ''
  2625.     category: 'Actors-Inspectors'!
  2626. SMACKInspector comment:
  2627. 'I represent a special kind of Inspector for Actor components.  I
  2628. change myself when the object inspected updates itself.'!
  2629.  
  2630.  
  2631. !SMACKInspector methodsFor: 'updating'!
  2632.  
  2633. update: aParameter
  2634.     "Assume everything has changed.  Update all dependents."
  2635.  
  2636.     self changed: aParameter! !
  2637. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2638.  
  2639. SMACKInspector class
  2640.     instanceVariableNames: ''!
  2641.  
  2642.  
  2643. !SMACKInspector class methodsFor: 'instance creation'!
  2644.  
  2645. inspect: anActor
  2646.     "Answer an instance of me to provide an inspector
  2647.      for anActor.  Ensure that my instance is a dependent of
  2648.      anActor."
  2649.  
  2650.     | temp |
  2651.     temp _ self new.
  2652.     anActor addDependent: temp.
  2653.     ^temp inspect: anActor! !
  2654.  
  2655. SMACKInspector subclass: #ActorDictionaryInspector
  2656.     instanceVariableNames: ''
  2657.     classVariableNames: 'ActorDictListMenu '
  2658.     poolDictionaries: ''
  2659.     category: 'Actors-Inspectors'!
  2660. ActorDictionaryInspector comment:
  2661. 'I am a special kind of SMACKInspector which knows how to inspect dictionaries.'!
  2662.  
  2663.  
  2664. !ActorDictionaryInspector methodsFor: 'field list'!
  2665.  
  2666. acceptText: aText from: aController
  2667.     | val |
  2668.     field == nil ifTrue: [^ false].
  2669.     val _ self evaluateText: aText string from: aController ifFail: [^ false].
  2670.     object at: field put: val.
  2671.     self changed: #text.
  2672.     ^ true!
  2673.  
  2674. fieldList
  2675.     "Answer a collection of the keys of the inspected dictionary."
  2676.  
  2677.     | keys | 
  2678.     keys _ object keys.
  2679.     keys detect: [:key | (key class == Symbol) not]
  2680.         ifNone: [^keys asSortedCollection]. "sort dictionaries with Symbol keys"
  2681.      ^keys asOrderedCollection!
  2682.  
  2683. fieldMenu
  2684.     "ActorDictionaryInspector flushMenus" 
  2685.  
  2686.     field == nil ifTrue: [^ActionMenu
  2687.                             labels: 'add field' withCRs
  2688.                             selectors: #(addField)].
  2689.     ActorDictListMenu == nil ifTrue: [
  2690.         ActorDictListMenu _ ActionMenu
  2691.                                 labels: 'inspect\add field\remove' withCRs
  2692.                                 lines: #(1)
  2693.                                 selectors: #(inspectField addField removeField)].
  2694.     ^ActorDictListMenu!
  2695.  
  2696. fieldValue
  2697.  
  2698.     ^object at: field!
  2699.  
  2700. printItems
  2701.     "Answer whether the elements of the fieldList need to be converted to strings"
  2702.  
  2703.     ^true! !
  2704.  
  2705. !ActorDictionaryInspector methodsFor: 'menu commands'!
  2706.  
  2707. addField
  2708.     | aString key |
  2709.     aString _ FillInTheBlank request: 'Enter key (an Actor identifier)'.
  2710.     aString isEmpty ifFalse: [
  2711.         key _ aString asSymbol.
  2712.         object add: (Association key: key value: nil).
  2713.         field _ key.
  2714.         self changed: #field]!
  2715.  
  2716. removeField
  2717.  
  2718.     (self confirm: 'Confirm removal of ', field printString) ifTrue: [
  2719.         object removeKey: field.
  2720.         field _ nil.
  2721.         object changed: #all.]! !
  2722. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2723.  
  2724. ActorDictionaryInspector class
  2725.     instanceVariableNames: ''!
  2726.  
  2727.  
  2728. !ActorDictionaryInspector class methodsFor: 'class initialization'!
  2729.  
  2730. flushMenus
  2731.     "ActorDictionaryInspector flushMenus."
  2732.  
  2733.     ActorDictListMenu _ nil! !
  2734.  
  2735. SMACKInspector subclass: #ActorCollectionInspector
  2736.     instanceVariableNames: ''
  2737.     classVariableNames: 'ActorCollectionMenu '
  2738.     poolDictionaries: ''
  2739.     category: 'Actors-Inspectors'!
  2740. ActorCollectionInspector comment:
  2741. 'I am a special kind of SMACKInspector which knows how to inspect collections.'!
  2742.  
  2743.  
  2744. !ActorCollectionInspector methodsFor: 'menu commands'!
  2745.  
  2746. addField
  2747.  
  2748.     field == nil
  2749.         ifTrue: [object addLast: nil]    "nothing selected"
  2750.         ifFalse: [self fieldIndex isNil
  2751.                 ifTrue: [object addFirst: nil]    "self selected"
  2752.                 ifFalse: [object add: nil beforeIndex: self fieldIndex]].
  2753.     self changed: #field!
  2754.  
  2755. removeField
  2756.     self fieldIndex isNil ifTrue: [^self].
  2757.     object removeAtIndex: self fieldIndex.
  2758.     self changed: #all! !
  2759.  
  2760. !ActorCollectionInspector methodsFor: 'field list'!
  2761.  
  2762. acceptText: aText from: aController
  2763.     | val |
  2764.     self fieldIndex isNil ifTrue: [^false].
  2765.     val _ self evaluateText: aText string from: aController ifFail: [^false].
  2766.     object at: self fieldIndex put: val.
  2767.     self changed: #text.
  2768.     ^true!
  2769.  
  2770. fieldIndex
  2771.     "Answer the index of the currently selected field, or nil if no index is selected."
  2772.  
  2773.     field isNil ifTrue: [^nil].
  2774.     field = 'self' ifTrue: [^nil].
  2775.     ^Integer readFromString: field!
  2776.  
  2777. fieldList
  2778.     "Answer a collection of strings with 'self' and the indices of the
  2779.      inspected ActorCollection."
  2780.  
  2781.     ^(Array with: 'self'),
  2782.         ((1 to: object size) collect: [:i | i printString])!
  2783.  
  2784. fieldMenu
  2785.     "ActorCollectionInspector flushMenus" 
  2786.  
  2787.     self fieldIndex isNil ifTrue:
  2788.         [^ActionMenu
  2789.             labels: 'add'
  2790.             selectors: #(addField)].
  2791.     ActorCollectionMenu == nil ifTrue:
  2792.         [ActorCollectionMenu _
  2793.             ActionMenu
  2794.                 labels: 'inspect\insert\remove' withCRs
  2795.                 lines: #(1)
  2796.                 selectors: #(inspectField addField removeField)].
  2797.     ^ActorCollectionMenu!
  2798.  
  2799. fieldValue
  2800.  
  2801.     field = 'self' ifTrue: [^object].
  2802.     ^object at: self fieldIndex! !
  2803. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2804.  
  2805. ActorCollectionInspector class
  2806.     instanceVariableNames: ''!
  2807.  
  2808.  
  2809. !ActorCollectionInspector class methodsFor: 'class initialization'!
  2810.  
  2811. flushMenus
  2812.     "Flush the menus."
  2813.     "ActorCollectionInspector flushMenus."
  2814.  
  2815.     ActorCollectionMenu _ nil! !
  2816.  
  2817. SMACKInspector subclass: #MailAddressInspector
  2818.     instanceVariableNames: ''
  2819.     classVariableNames: 'MailAddressMenu '
  2820.     poolDictionaries: ''
  2821.     category: 'Actors-Inspectors'!
  2822. MailAddressInspector comment:
  2823. 'I am a special kind of inspector for Mail addresses, which knows how
  2824. to inspect the corresponding actor.'!
  2825.  
  2826.  
  2827. !MailAddressInspector methodsFor: 'field list'!
  2828.  
  2829. fieldMenu
  2830.     "Answer with an action menu for the field view."
  2831.     "MailAddressInspector flushMenus."
  2832.  
  2833.     field == nil ifTrue: [^ActionMenu
  2834.                             labels: 'inspect actor'
  2835.                             selectors: #(inspectActor)].
  2836.     MailAddressMenu == nil ifTrue:
  2837.         [MailAddressMenu _ ActionMenu
  2838.                             labels: 'inspect\inspect actor' withCRs
  2839.                             selectors: #(inspectField inspectActor)].
  2840.     ^MailAddressMenu! !
  2841.  
  2842. !MailAddressInspector methodsFor: 'menu commands'!
  2843.  
  2844. inspectActor
  2845.     "Inspect the actor referred to by the object."
  2846.  
  2847.     object class == MailAddress ifTrue: [
  2848.         (MailAddress mailer table at: object ifAbsent: [nil]) inspect]! !
  2849. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2850.  
  2851. MailAddressInspector class
  2852.     instanceVariableNames: ''!
  2853.  
  2854.  
  2855. !MailAddressInspector class methodsFor: 'class initialization'!
  2856.  
  2857. flushMenus
  2858.     "Flush the menu."
  2859.     "MailAddressInspector flushMenus."
  2860.  
  2861.     MailAddressMenu _ nil! 
  2862.  
  2863. !TextCollector subclass: #ActorTextCollector
  2864.     instanceVariableNames: ''
  2865.     classVariableNames: 'DefaultBehaviour TheTextCollector '
  2866.     poolDictionaries: ''
  2867.     category: 'Actors-Interface'!
  2868. ActorTextCollector comment:
  2869. 'I support special instance creation methods for a `transcript'' for actors.'!
  2870.  
  2871. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2872.  
  2873. ActorTextCollector class
  2874.     instanceVariableNames: ''!
  2875.  
  2876.  
  2877. !ActorTextCollector class methodsFor: 'actor creation'!
  2878.  
  2879. newTranscript
  2880.     "Create a global Actor called ActorTranscript, which behaves as
  2881.      a transcript for actors."
  2882.     "ActorTextCollector newTranscript."
  2883.  
  2884.     self newTranscript: DefaultBehaviour!
  2885.  
  2886. newTranscript: behaviour
  2887.     "Create a global Actor which behaves as a transcript, with
  2888.      behaviour from the argument."
  2889.     "ActorTextCollector newTranscript: ActorTextCollector defaultBehaviour."
  2890.  
  2891.     Smalltalk at: #ActorTranscript put: (Actor withBehaviour: behaviour).!
  2892.  
  2893. open
  2894.     "Create and schedule a view on my global instance."
  2895.     "ActorTextCollector open."
  2896.  
  2897.     TextCollectorView open: TheTextCollector label: 'Actor (', ActorTranscript printString, ') Transcript'! !
  2898.  
  2899. !ActorTextCollector class methodsFor: 'class initialization'!
  2900.  
  2901. initialize
  2902.     "Initialize the class variables."
  2903.     "ActorTextCollector initialize."
  2904.  
  2905.     TheTextCollector _ self new.
  2906.     DefaultBehaviour _ Behaviour block: [:slf :acq :com | 
  2907.         com name == #cr ifTrue: [TheTextCollector cr].
  2908.         com name == #tab ifTrue: [TheTextCollector tab].
  2909.         com name == #show ifTrue: [
  2910.                     TheTextCollector show: (com at: 1)].
  2911.         com name == #clear ifTrue: [TheTextCollector clear].
  2912.         com name == #flash ifTrue: [TheTextCollector flash; refresh]]! !
  2913.  
  2914. !ActorTextCollector class methodsFor: 'class access'!
  2915.  
  2916. defaultBehaviour
  2917.     "Answer with the class variable representing the default behaviour
  2918.      of instances of the receiver."
  2919.     "ActorTextCollector defaultBehaviour."
  2920.  
  2921.     ^DefaultBehaviour! !
  2922.  
  2923. !ActorTextCollector class methodsFor: 'examples'!
  2924.  
  2925. example1
  2926.     "ActorTextCollector example1."
  2927.  
  2928.     ActorTranscript sendMessage: #cr.
  2929.     ActorTranscript sendMessage: #show with: 'Hello world!!'.!
  2930.  
  2931. example2
  2932.     "ActorTextCollector example2."
  2933.  
  2934.     ActorTranscript sendMessage: #clear.
  2935.     ActorTranscript sendMessage: #show with: 'Hello again!!'.
  2936.     ActorTranscript sendMessage: #flash.!
  2937.  
  2938. example3
  2939.     "ActorTextCollector example3."
  2940.  
  2941.     ActorTranscript sendMessage: #clear.
  2942.     ActorTranscript sendMessage: #show with: 'First Message, '.
  2943.     ActorTranscript sendMessage: #show with: 'Second Message '.
  2944.     ActorTranscript sendMessage: #show with: 'and Third Message'.! !
  2945.  
  2946. ActorTextCollector initialize!
  2947. Object subclass: #RecursiveFactorial
  2948.     instanceVariableNames: ''
  2949.     classVariableNames: ''
  2950.     poolDictionaries: ''
  2951.     category: 'Actors-Smalltalk examples'!
  2952. RecursiveFactorial comment:
  2953. 'I represent a factorial calculator, using a recursive algorithm.'!
  2954.  
  2955.  
  2956. !RecursiveFactorial methodsFor: 'factorial'!
  2957.  
  2958. factorial: n
  2959.     "Perform a recursive factorial computation."
  2960.  
  2961.     n <= 1
  2962.         ifTrue: [^n]
  2963.         ifFalse: [^n * (self factorial: (n - 1))]! !
  2964. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2965.  
  2966. RecursiveFactorial class
  2967.     instanceVariableNames: ''!
  2968.  
  2969.  
  2970. !RecursiveFactorial class methodsFor: 'examples'!
  2971.  
  2972. example1
  2973.     "RecursiveFactorial example1."
  2974.  
  2975.     Transcript cr; show: (RecursiveFactorial new factorial: 20) printString!
  2976.  
  2977. example2
  2978.     "RecursiveFactorial example2."
  2979.  
  2980.     | fac |
  2981.     fac _ RecursiveFactorial new.
  2982.     Transcript cr; show: (Time millisecondsToRun: [
  2983.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  2984.  
  2985. Object subclass: #DivideAndConquerFactorial
  2986.     instanceVariableNames: ''
  2987.     classVariableNames: ''
  2988.     poolDictionaries: ''
  2989.     category: 'Actors-Smalltalk examples'!
  2990. DivideAndConquerFactorial comment:
  2991. 'I represent a factorial computation, using a doubly recursive
  2992. `divide-and-conquer'' algorithm.'!
  2993.  
  2994.  
  2995. !DivideAndConquerFactorial methodsFor: 'factorial'!
  2996.  
  2997. factorial: n
  2998.     "Answer with n factorial, using a recursive divide-and-conquer algorithm."
  2999.  
  3000.     ^self rangeProductLow: 1 high: n!
  3001.  
  3002. rangeProductLow: lo high: hi
  3003.     "Answer with the product of the numbers between lo and hi."
  3004.  
  3005.     | mid |
  3006.     (lo = hi) ifTrue: [^lo].
  3007.     (lo > hi) ifTrue: [^1].
  3008.     (lo < hi) ifTrue: [
  3009.         mid _ (lo + hi ) // 2.
  3010.         ^(self rangeProductLow: lo high: mid) * (self rangeProductLow: mid + 1 high: hi)]! !
  3011. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3012.  
  3013. DivideAndConquerFactorial class
  3014.     instanceVariableNames: ''!
  3015.  
  3016.  
  3017. !DivideAndConquerFactorial class methodsFor: 'examples'!
  3018.  
  3019. example1
  3020.     "DivideAndConquerFactorial example1."
  3021.  
  3022.     Transcript cr; show: (DivideAndConquerFactorial new factorial: 20) printString!
  3023.  
  3024. example2
  3025.     "DivideAndConquerFactorial example2."
  3026.  
  3027.     | fac |
  3028.     fac _ DivideAndConquerFactorial new.
  3029.     Transcript cr; show: (Time millisecondsToRun: [
  3030.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  3031.  
  3032. Object subclass: #IterativeFactorial
  3033.     instanceVariableNames: 'current '
  3034.     classVariableNames: ''
  3035.     poolDictionaries: ''
  3036.     category: 'Actors-Smalltalk examples'!
  3037. IterativeFactorial comment:
  3038. 'I represent a factorial calculator, using an interative algorithm.'!
  3039.  
  3040.  
  3041. !IterativeFactorial methodsFor: 'factorial'!
  3042.  
  3043. factorial: n
  3044.     "Perform an iterative factorial computation."
  3045.  
  3046.     current _ 1.
  3047.     ^self iterate: n!
  3048.  
  3049. iterate: n 
  3050.     "Perform an iterative factorial step."
  3051.  
  3052.     (n <= 1)
  3053.         ifTrue: [^current]
  3054.         ifFalse: [
  3055.             current _ current * n.
  3056.             ^self iterate: (n - 1)]! !
  3057. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3058.  
  3059. IterativeFactorial class
  3060.     instanceVariableNames: ''!
  3061.  
  3062.  
  3063. !IterativeFactorial class methodsFor: 'examples'!
  3064.  
  3065. example1
  3066.     "IterativeFactorial example1."
  3067.  
  3068.     Transcript cr; show: (IterativeFactorial new factorial: 20) printString.!
  3069.  
  3070. example2
  3071.     "IterativeFactorial example2."
  3072.  
  3073.     | fac |
  3074.     fac _ IterativeFactorial new.
  3075.     Transcript cr; show: (fac factorial: 3) printString.
  3076.     Transcript cr; show: (fac factorial: 10) printString!
  3077.  
  3078. example3
  3079.     "IterativeFactorial example3."
  3080.  
  3081.     | fac |
  3082.     fac _ IterativeFactorial new.
  3083.     Transcript cr; show: (Time millisecondsToRun: [
  3084.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  3085.  
  3086. Object subclass: #Surrogate
  3087.     instanceVariableNames: 'proxy '
  3088.     classVariableNames: ''
  3089.     poolDictionaries: ''
  3090.     category: 'Actors-Smalltalk examples'!
  3091. Surrogate comment:
  3092. 'I represent a simple implementation of surrogates.'!
  3093.  
  3094.  
  3095. !Surrogate methodsFor: 'synchronising'!
  3096.  
  3097. doesNotUnderstand: aMessage
  3098.     "Any message to a Surrogate will end up here."
  3099.  
  3100.     ^proxy perform: aMessage selector withArguments: aMessage arguments! !
  3101.  
  3102. !Surrogate methodsFor: 'private'!
  3103.  
  3104. setProxy: anObject
  3105.     "Set the proxy to be anObject."
  3106.  
  3107.     proxy _ anObject! !
  3108. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3109.  
  3110. Surrogate class
  3111.     instanceVariableNames: ''!
  3112.  
  3113.  
  3114. !Surrogate class methodsFor: 'instance creation'!
  3115.  
  3116. newOn: anObject
  3117.     "Create a new instance of the receiver, being a surrogate for anObject."
  3118.  
  3119.     ^self new setProxy: anObject! !
  3120.  
  3121. !Surrogate class methodsFor: 'class initialization'!
  3122.  
  3123. initialize
  3124.      "must avoid the checks"
  3125.  
  3126.     superclass _ nil
  3127.  
  3128.     "Surrogate initialize."! !
  3129.  
  3130. Surrogate initialize!
  3131.